ACM2016级新生第三周训练赛
本次是弱校题解-比赛链接
题目还是比较基础,比较简单。认真补题,学会学习。
A -人见人爱A^B
题解: 求 A的B次方,我们可以用循环进行累乘操作,进而计算出次方.因为题目要求只需要求出最后三位,所以每次对 1000 求余数,最后输出即可。
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) return 0; int ans=1,i; for(i=1;i<=m;i++) { ans=ans*n; ans%=1000; } printf("%d\n",ans); } return 0; }
B -数列有序!
题解:详见代码,输出的时候判断 大于等于前一个数且小于等于后一个数,满足之后输出,输出之后不要重复输出,所以用了一个标记变量标记这个数字是否已经输出。
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #define INF 2e9 int a[105]; int ans[105]; int main() { // printf("%d\n",INF); int n,m; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) return 0; int i,flag=1; a[0]=-INF; a[n+1]=INF; for(i=1; i<=n; i++) scanf("%d",&a[i]); int k=1; for(i=1;i<=n+1;i++) { if(m>=a[i-1]&&m<=a[i]&&flag) { ans[k++]=m; flag=0; } ans[k++]=a[i]; } for(i=1;i<k-1;i++) { if(i==k-2) printf("%d\n",ans[i]); else printf("%d ",ans[i]); } } return 0; }
C -密码
思路:首先判断长度是否合格,不合格输出 NO ,合格再进行下一步的判断。判断字符种类是否大于等于3种。我的方法是用4个变量标记一下是否存在?到最后判断一下。思路就酱紫。具体实现看看代码吧。
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #define MAXSIZE 100000+10 char str[MAXSIZE]; int main() { int ncase; scanf("%d",&ncase); while(ncase--) { scanf("%s",str); int len=strlen(str); int f1=0,f2=0,f3=0,f4=0; if(len>=8&&len<=16) { int i; for(i=0;i<len;i++) { if(str[i]>='A'&&str[i]<='Z') f1=1; if(str[i]>='a'&&str[i]<='z') f2=1; if(str[i]>='0'&&str[i]<='9') f3=1; if(str[i]=='~'||str[i]=='!'||str[i]=='@'||str[i]=='#'||str[i]=='$'||str[i]=='%'||str[i]=='^') f4=1; } if(f1+f2+f3+f4>=3) printf("YES\n"); else printf("NO\n"); } else printf("NO\n"); } return 0; }
D -验证角谷猜想
思路:按照题目意思模拟一遍,符合要求的数字存在一个数组里面,最后判断数组中的个数是否是0?不是零就输出,注意是两个数之间有一个空格,行末尾是没有空格的。注意这个就好了。
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #define MAXSIZE 100000+10 int a[MAXSIZE]; int main() { int ncase; scanf("%d",&ncase); while(ncase--) { int n,k=0; scanf("%d",&n); while(1) { if(n==1) break; if(n%2==1) { a[k++]=n; n=n*3+1; } else { n/=2; } } if(k==0) printf("No number can be output !\n"); else { int i; for(i=0;i<k;i++) { if(i==k-1) printf("%d\n",a[i]); else printf("%d ",a[i]); } } } return 0; }
E -寻找素数对 思路:第一步筛法打素数表,因为需要找距离最近的素数对,所以枚举(用循环)所有相邻的两个素数。
#include <stdio.h> #include <string.h> int main() { int a[10005],i,j; memset(a,0,sizeof(a));// 0 代表是素数 a[0]=a[1]=1; for (i = 2 ; i <= 10000 ; i++) //筛法打素数表 { if ( a[i] == 0) { for ( j = i + i ; j < 10005 ; j += i) a[j] = 1; } } int m,n; while(scanf("%d",&m)!=EOF) { n = m/2; for ( i = n; i > 5; i--) { if ((a[i] == 0 && a[m-i] == 0)) { printf("%d %d\n",i,m-i); break; } } } return 0; }
F - 求数列的和
思路:直接模拟,循环
#include<stdio.h> #include<math.h> int main() { int i; double n,m,sum; while(scanf("%lf %lf",&n,&m)!=EOF) { sum=0; for(i=0;i<m;i++) { sum+=n; n=sqrt(n); } printf("%.2lf\n",sum); } return 0; }
G -做减法
分析:知道题目就是算a-b,只是输出的时候,每三个数字之间用一个英文状态下的逗号隔开。
思路:先算出a-b的值,然后把这个数字的各个位存在一个数组里面,然后对于数组下标能被 3 整除的数的后面加上一个逗号就可以了。注意0也能够被3整除,但是最后一个是不需要逗号的。还有值得注意 的是如果这个数字为0需要特殊判断一下。综上所述,代码见下面。
#include<stdio.h> int main() { int a,b; while(scanf("%d%d",&a,&b)!=EOF) { int ans=a-b,k=0,i; if(ans<0) printf("-"),ans=-ans; int num[40]; if(ans==0) printf("0"); else { while(ans) { num[k++]=ans%10; ans/=10; } for(i=k-1; i>=0; i--) { printf("%d",num[i]); if(i%3==0&&i>0) printf(","); } } printf("\n"); } return 0; }
H -A hard Aoshu Problem
思路: 本题解法多样我写一个就够了。用一个数组来统计某一个数字出现的次数。因为数字是从 -100开始的,所以我在标记的时候这个数字加100 作为标记数组的下标。最后从前往后找出一个最大值,因为题目要求值要尽量小,所以我们更新最大值的时候,只有在后面的数字大于前面的才进行更新,相等的时候也不更新最大值。
所以详见代码:
#include<stdio.h> #include<string.h> int a[250]; int main() { int n; while(scanf("%d",&n)!=EOF) { memset(a,0,sizeof(a)); int i; for(i=0;i<n;i++) { int num; scanf("%d",&num); a[num+100]++; } int maxn=-1,pos=0; for(i=0;i<=200;i++) { if(a[i]>maxn) maxn=a[i],pos=i; } printf("%d %d\n",pos-100,maxn); } return 0; }
I -18岁生日
思路: 如果是在2月29出生的一定没有18岁的生日,因为18不能够被4整除。所以XXX;那么不是2月29的应该如何计算?我们假设每年都有365天,那么总共会有 365*18 这么多天,因为有闰年所以判断会经过多少个闰年的2月。如果出生在3月及以后那么就不会经过当年的2月,所以当出生月份 >= 3 ,那么就从下一年开始计算。最后两者相加即为最终答案。
#include <stdio.h> int main() { int n,i,y,m,d,sum; scanf("%d",&n); while(n--) { sum=0; scanf("%d-%d-%d",&y,&m,&d); if(m==2&&d==29) { printf("-1\n"); continue; } if(m>=3) y++; for(i=y; i<y+18; i++) if(i%4==0&&i%100!=0||i%400==0) sum++; printf("%d\n",365*18+sum); } return 0; }
I -18岁生日
作者:LZQ
大致思路:
可知n可分为两种:
1.n==1,只输出输出中心花色字符
2.n!=1时
观察可知,共有n排,n列,
且第一排和最后一排均是空格,n-2个中心花色字符或外筐花色字符,空格;
当(n-1)%2==0时是中心花色字符,当(n-1)%2==1时是外筐花色字符;
其他排即第i排从第一个字符到第i个字符外筐花色字符和中心花色字符交替,
第i+1个字符到第n-i个字符均为外筐花色字符或中心花色字符,
第n-i+1到第n个字符依然是外筐花色字符和中心花色字符交替。
且整个图案关于第n/2+1排对称,可用取余来交换输出这些字符。
由此规律可写出代码
#include<stdio.h> int main() { int n,flag=0; char c1,c2,temp; while(scanf("%d %c %c",&n,&c1,&c2)!=EOF) { if(flag) //题目要求每两组数据间要有一个换行,即除了以一组数据外,其他数据输出前都有一个换行 printf("\n"); int i,j,k; if(n==1)//特判n==1的情况 printf("%c\n",c1); if((n-1)/2%2==0) temp=c1,c1=c2,c2=temp; //观察可知若(n-1)/2为偶数,则第一排和最后一排均为c2,否则第一排和最后一排均为c1 if(n!=1) //若n不为1 for(i=1; i<=n; i++) { k=i; if(i>n/2+1) k=n-i+1; if(i==1||i==n) { printf(" "); for(j=1; j<=n-2; j++) printf("%c",c2); printf(" "); } else for(j=1; j<=n; j++) { if(j>k&&j<=n-k) { if(k&1) printf("%c",c2); else printf("%c",c1); } else { if(j&1) printf("%c",c2); else printf("%c",c1); } } printf("\n"); } flag=1; } }
注:赛后需认真补题,不然题目就浪费了。