ACM学习总结之素数与串问题

来源:互联网 发布:django 生鲜教程源码 编辑:程序博客网 时间:2024/05/18 07:57

ACM学习总结之素数与串问题

--------EOL代表此处输出换行符'\n',EOF代表数据输出结束-------

1.调酒师

作为调酒师的西瓜,在生日当天,请了N位好朋友来家中作客,当然免不了大展身手。西瓜在超市买了A瓶酒,每瓶酒有B毫升,买了C个柠檬,把每一个柠檬切成D片,还买了E克盐。西瓜要调的酒,每一杯需要F毫升的原味酒、一片柠檬以及G克盐。西瓜希望每个朋友分到同样杯数的酒,同时西瓜又希望每个人分到的酒尽可能多。问每个朋友能分到几杯调好的酒。

输入声明一个整数t,表示测试数据组数(1<=t<=100)
对于每一组数据,共一行,有8个整数,逗号隔开,分别为N,A,B,C,D,E,F,G,其中这7个整数都在[0, 1000]内,保证N不为0。

输出说明:每一组测试数据,输出一个整数,表示每个朋友分到的酒的杯数。

输入样例:

2[EOL] 
2[SP]4[SP]7[SP]3[SP]4[SP]10[SP]2[SP]1[EOL] 
1[SP]1000[SP]1000[SP]1000[SP]1000[SP]1000[SP]1[SP]1[EOF] 

输出样例:

5[EOL] 
1000[EOL] 
[EOF] 
程序:

#include<stdio.h>int main (){int k,t,m,n,N,A,B,C,D,E,F,G;scanf("%d",&t);for(k=0;k<t;k++){scanf("%d %d %d %d %d %d %d %d",&N,&A,&B,&C,&D,&E,&F,&G);m=(((A*B)/F)<(E/G)?((A*B)/F):(E/G));n=(m<(C*D)?m:(C*D));printf("%d",n/N);}return 0;}

注意:各个数之间的关系,如果在计算的时候需要上取整或者下取整,可以使用ceil()或floor()函数,返回值均为double。

2.求素数 :用筛选法求(1,n]之内的全部素数

输入说明:行1:一个整数n,n∈[2,100000]

输出说明:每行输出一个素数,由小到大排列

输入样例:

20[EOL] 
[EOF] 

输出样例:

2[EOL] 
3[EOL] 
5[EOL] 
7[EOL] 
11[EOL] 
13[EOL] 
17[EOL] 
19[EOL] 
[EOF] 
程序:

#include<stdio.h>#include<math.h>int main(){int m,n,h,k;scanf("%d",&n);if(n==2)printf("2\n");if(n>=3)printf("2\n3\n");for(m=2;m<=n;m++){k=sqrt(m);for(h=2;h<=k;h++){if(m%h==0)break;if(h>=k)printf("%d\n",m);}}return 0;}
注意:对2,3的特判!!!

3.素数判断:输入1000以内的数,判断是否为为素数,是则输出“Yes”,否则输出“No”. 注意:1不是素数

输入说明:第一行输入t(t<=10),接下来t行为输入的数。

输出说明:每个数输出对应结果

输入样例:

2[EOL] 
2[EOL] 
4[EOL] 
[EOF] 
输出样例:
Yes[EOL] 
No[EOL] 
[EOF] 
程序:
#include<stdio.h>#include<math.h>int main(){int t,n,k,m,h;scanf("%d",&t);for(m=0;m<t;m++) {scanf("%d",&n);if(n==1){printf("No\n");continue;} if(n==2||n==3){printf("Yes\n");continue;}    if (n>3)    {k=sqrt(n);for(h=2;h<=k;h++) if(n%h==0)break; if(h<=k)printf("No\n");else printf("Yes\n");}} return 0;} 
注意:特判1,2,3并且注意素数判断关系!!!
2,3总结:采用素数筛法,常见的有埃式筛法、线性筛法(欧拉筛法)
埃式筛法:依次处理2,3...的倍数,直到处理到ceil(sqrt(N)),其缺点在于会多次处理某些数的公倍数,如20
4.判断回文 :一个字符串从左向右读和从右向左读是一样的,我们称这样的字符串为回文串。 例如:aba,abccba都是回文串。 问题:现在给你一个字符串,判断它是否是回文串。
输入说明:多组数据,以EOF结束。输入字符串str长度不超过100
输出说明:判断该字符串是否为回文串,是则输出"YES",否则输出"NO".
输入样例:
aba[EOL] 
aabbc[EOL] 
[EOF] 
输出样例:
YES[EOL] 
NO[EOL] 
[EOF] 
程序:
#include<stdio.h>#include<string.h>int main(){char str[105];while(scanf("%s",str)!=EOF){int i,p=1;int len=strlen(str); for(i=0;i<(len+1)/2;i++){if(str[i]!=str[len-1-i])p=0;}if(p==1)printf("YES\n");else printf("NO\n");}return 0;}
注意:对p的声明要放到while里面去!!!还有,输出是YES不是Yes!!!
5.分解质因数:给出一个正整数m, 将其分解成质数相乘的形式,即 m=m1*m2*m3*....*mk. 其中mi为质数,并且满足m1<=m2<=m3<=....<=mk。若m本身就是质数,则直接输出m=m即可。
输入说明:输入包括多组测试数据,每组测试数据占一行,并且只有一个正整数m,当m=0时,表示输入结束。

输出说明:对每组测试数据输出一个结果,并占一行。

输入样例:

12[EOL] 
5[EOL] 
2310[EOL] 
0[EOL] 
[EOF] 
输出样例:

12=2*2*3[EOL] 
5=5[EOL] 
2310=2*3*5*7*11[EOL] 
[EOF] 
程序:

#include<stdio.h>int main(){int n,i;while(scanf("%d",&n)&&!(n==0))  {printf("%d=",n);  for(i=2;i<=n;i++)while(n!=i){if(n%i==0){printf("%d*",i);n=n/i;}else break;}printf("%d\n",n);}   return 0;} 

注意:输出格式一点要对!!!

补充题:若一个数的所有因子之和恰好等于其本身,称此数为完数。请输出1000以内的所有完数,输出样例:6 its factors are 1 2 3

程序:

#include<stdio.h>int main(){int m,s,i;for(m=2;m<1000;m++){s=0;for(i=1;i<m;i++)if((m%i)==0)s+=i;if(s==m){printf("%d,its factors are ",m);for(i=1;i<m;i++)if(m%i==0)printf("%d\t",i);printf("\n");}}return 0;}
此题要注意后续的输出如何输出。

6.大数加法:求两个不超过200 位的非负整数的和。

输入说明:有两行,每行是一个不超过200 位的非负整数,没有多余的前导0。
输出说明:一行,即相加后的结果。结果里不能有多余的前导 0,即如果结果是342,那么就不能输出为 0342

输入样例:

88888888888888888888[EOL] 
33333333333333333333[EOL] 
[EOF] 
输出样例:

122222222222222222221[EOF] 
程序:

#include<stdio.h>#include<string.h>#define M 200int main(){char num1[M+1];char num2[M+1];char sum[M+2];char s1[M+1];char s2[M+1];while(scanf("%s %s",num1,num2)!=EOF) {   int len1=0,len2=0,i=0,j=0,m=0,SUM=0,h=0,t=0;len1=strlen(num1),len2=strlen(num2);j=0;for(i=len1-1;i>=0;--i){s1[j++]=num1[i];}s1[j]='\0';j=0;for(i=len2-1;i>=0;--i){s2[j++]=num2[i];}m=(len1>len2)?len1:len2;if(len1<len2){for(i=len1;i<len2;++i)s1[i]='0';s1[len2]='\0';}else if(len1>len2){for(i=len2;i<len1;++i)s2[i]='0';s2[len1]='\0';}for(i=0;i<m;i++){ SUM=s1[i]-'0'+s2[i]-'0'+h;if(SUM>9){if(i==(m-1)){t=1;}h=1;sum[i]=SUM-10+'0'; }  else {h=0;sum[i]=SUM+'0';}}if(t==1){sum[m++]=h+'0';}sum[m]='\0';  for(i=m-1;i>=0;--i){putchar(sum[i]);}printf ("\n");}return 0;}

注意:对t的声明必须要放在while里面,这个和第4题是一样的

补充:杭电1002大数加法题

input:The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line consists of two positive integers, A and B. Notice that the integers are very large, that means you should not process them by using 32-bit integer. You may assume the length of each integer will not exceed 1000.

output:For each test case, you should output two lines. The first line is "Case #:", # means the number of the test case. The second line is the an equation "A + B = Sum", Sum means the result of A + B. Note there are some spaces int the equation. Output a blank line between two test cases.

sample input:

2

1 2

112233445566778899 998877665544332211

sample output:

Case 1:

1 + 2 = 3


Case 2:

112233445566778899 + 998877665544332211 = 1111111111111111110

程序:

1.对上面的程序稍作更改:把while语句改成for循环,并加上:

printf("Case %d:\n",k+1);printf("%s + %s = ",num1,num2);
记得输出结果中空行,在最后一行中,只需输出一个空行即可,用下列语句控制:

printf ("\n");if(k<T-1)printf ("\n");
2.

#include<stdio.h>  #include<string.h>  int shu(char a)  {      return (a-'0');  }  int main(){      char a[1000],b[1000];      int num[1001];      int n,i,j=1,al,bl,k,t;      scanf("%d",&n);      while(n--)      {          if(j!=1)         printf("\n");         scanf("%s",a);         al=strlen(a);         scanf("%s",b);         bl=strlen(b);         k=(al>bl)?al:bl;         for(i=0;i<=k;i++)       num[i]=0;         t=k;         for(k;al>0&&bl>0;k--)         {             num[k]+=shu(a[--al])+shu(b[--bl]);               if(num[k]/10)             {                 num[k-1]++;                 num[k]%=10;             }         }         while(al>0)        {              num[k--]+=shu(a[--al]);              if(num[k+1]/10)             {                 num[k]++;                 num[k+1]%=10;             }         }         while(bl>0)         {              num[k--]+=shu(b[--bl]);              if(num[k+1]/10)             {                 num[k]++;                 num[k+1]%=10;             }         }           printf("Case %d:\n",j++);         printf("%s + %s = ",a,b);         for(i=0;i<=t;i++)         {             if(i==0&&num[i]==0)             i++;             printf("%d",num[i]);         }         printf("\n");     }     return 0;  }  

这是用字符串模拟的方式,来计算大数加法,也可以用数组来进行计算。还有若遇到0000000000000的情况,应进行特判。笔者后续会补充。并将补充素数筛选法,大数减法、乘除法的文章。


原创粉丝点击