题解
A
简单的签到题,会输出语句就可以写。
#include<stdio.h>
int main()
{
printf("I will be an acmer!");
return 0;
}
B
会条件语句就会写。首先可以判断输入的年份是否是闰年,当年份不是100的整数倍时,它需要是4的倍数,当它是100的整数倍时,它需要是400的倍数吗,了解这个之后,判断语句就很好写了。接下来判断年份是否满足其中恰好两位是三的倍数,只要每次将年份除以10,再取余10,重复四次,就可以从一个四位数中找出每位数字,再判断一下它是否是3的倍数就好了
#include <stdio.h>
int solve()
{
int y;
scanf("%d",&y);
if((y%4!=0 || y%100==0) && y%400!=0)
return 0;
int cnt=0;
if(y%10%3==0) cnt++;
y/=10;
if(y%10%3==0) cnt++;
y/=10;
if(y%10%3==0) cnt++;
y/=10;
if(y%10%3==0) cnt++;
if(cnt==2) return 1;
return 0;
}
int main()
{
if(solve())
printf("yse");
else
printf("no");
return 0;
}
C
这道题的关键是如何判断一个字符是否是阿拉伯数字,可以用下面这个简单的式子判断:a<'0' || a>'9'。我们知道,字符的存储方式跟整形一样,在存储空间中是以ASCII码的方式存储的,因此,只要这个字符的ASCII码比'0'小,比'9'大,它就一定不是阿拉伯数字。然后再写个简单的循环判断一下就行了。
#include<stdio.h>
int main()
{
int n;
scanf("%d",&n);
int cnt=0;
getchar();
for(int i=0;i<n;i++)
{
char a;
scanf("%c",&a);
if(a<'0' || a>'9') cnt++;
}
printf("%d",cnt);
return 0;
}
D
用暴力搜索的方法即可。首先输入字符串,注意样例的格式,如果你用的也是scanf的方法输入,需要用getchar()将回车吞掉避免将回车当做字符判断。接着就是分别判断横向和纵向,用双层循环把每一个字符都搜索一遍,看看它以及它后面的字符是否符合要求,如果符合,就让数量加1,最后输出总数量即可。
#include<stdio.h>
const int N=1010;
char str[N][N];
void solve()
{
int n,m;
scanf("%d %d",&n,&m);
getchar();
int cnt=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
scanf("%c",str[i]+j);
}
getchar();
}
for(int i=0;i<m;i++)
{
for(int j=0;j<n-7;j++)
{
if(str[j][i]=='y'&&str[j+1][i]=='u'&&str[j+2][i]=='a'&&str[j+3][i]=='n'&&str[j+4][i]=='s'&&str[j+5][i]=='h'&&str[j+6][i]=='e'&&str[j+7][i]=='n')
{
cnt++;
}
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m-7;j++)
{
if(str[i][j]=='y'&&str[i][j+1]=='u'&&str[i][j+2]=='a'&&str[i][j+3]=='n'&&str[i][j+4]=='s'&&str[i][j+5]=='h'&&str[i][j+6]=='e'&&str[i][j+7]=='n')
{
cnt++;
}
}
}
printf("%d\n",cnt);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
solve();
}
return 0;
}
E
这道题考察了一些搜索时的处理方式,但是并没有考察搜索。首先就是在寻找路线时,每次都要把各个方向都搜一遍,那么就可以用一个比较方便的滚轮数组dx[4]={0,0,1,-1},dy[4]={1,-1,0,0},我们会发现,只要用一个循环循环四遍,就可以完美的把每个方向都搜一遍。
还有一个比较重要的点就是搜过的路线一定要做一个标记,这样再次搜到时就可以略过去,避免造成死循环。
剩下的就是用循环把所有点都搜一下就可以了
#include<stdio.h>
const int N=1010;
int a[N][N];
bool st[N][N];
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
int main()
{
int n,m;
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
scanf("%d",a[i]+j);
}
int i=0,j=0;
st[0][0]=1;
printf("0 0\n");
while(i!=n-1 || j!=m-1)
{
for(int k=0;k<4;k++)
{
int x=i+dx[k],y=j+dy[k];
if(x>=0 && x<n && y>=0 && y<m && a[x][y]==1 && !st[x][y])
{
i=x,j=y;
st[x][y]=1;
printf("%d %d\n",x,y);
break;
}
}
}
return 0;
}
F
这道题主要考察了递推的思想。假设现在在放第i层,a[i]表示第i层放的是卷饼,b[i]表示第i层放的是烤肉,c[i]表示第i层放的是酸黄瓜,那么很显然,卷饼的上一层可以放卷饼、烤肉、酸黄瓜,因此a[i]=a[i-1]+b[i-1]+c[i-1];烤肉的上一层可以放卷饼,因此b[i]=a[i-1];酸黄瓜的上一层可以放卷饼、烤肉,所以c[i]=a[i-1]+b[i-1]。第一层只能放卷饼,因此初始状态为a[1]=1,b[1]=0,c[1]=0;最后一层只能放卷饼,因此最后答案应该是a[n]的值
#include<stdio.h>
typedef long long LL;
const int N=35;
LL a[N],b[N],c[N];
int n;
int main()
{
scanf("%d",&n);
a[1]=1,b[1]=0,c[1]=0;
for(int i=2;i<=n;i++)
{
a[i]=a[i-1]+b[i-1]+c[i-1];
b[i]=a[i-1];
c[i]=a[i-1]+b[i-1];
}
printf("%d",a[n]);
return 0;
}
G
这道题考察了一个比较基础的算法————二分法,相信大家以前在数学上就接触过这种方法。二分法的主要思想就是每次通过对区间中间点的判断来排除掉一半的区间,可以以优秀的时间复杂度查找到元素在区间的位置。本题就是一个十分经典的二分问题,在每次中间点的值a[mid]小于k时,就去掉左半边的区间,否则去掉右半边的区间,最后只剩一个点时,这个点就是数组中满足a[i]小于k的最大的i值。同样的,如果将条件改为a[mid]小于等于k,那么最后得到的点就是满足a[i]小于等于k的最大的i值。那么将两次得到的值相减,就可以得到数组中等于k的数有多少个了。
#include<iostream>
using namespace std;
const int N=100000010;
int n,k;
int a[N];
int s1(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (a[mid]<k) l = mid;
else r = mid - 1;
}
return l;
}
int s2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (a[mid]<=k) l = mid;
else r = mid - 1;
}
return l;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin >> n >> k;
for(int i=0;i<n;i++)
cin >> a[i];
cout << s2(0,n-1)-s1(0,n-1);
return 0;
}