一如既往地记录写程序过程中遇到的问题
以下是乱序的问题总结
D. 实验4_12_遍历搜寻
运行时间限制: 1000 运行内存限制: 65536
作者: bupt_admin 是否specialjudge: False
题目描述
问题描述:
已知整数a、b、c。你的任务是求出区间[a,b]内的整数,满足该数与“该数的所有因数(不包括本身但包括1,1的因数和按0处理)相加之和”的差的绝对值小于等于c的数字。例如27的因数是1、3、9。那么27与27的所有因数和的差为:27-(1+3+9)=14。
输入与输出要求:
输入三个整数a、b、c。a、b代表所求区间范围,满足1<=a<=b<=10000,c代表限制条件,c>=0。输出满足条件的整数,每五个数为一行,整数之间用tab分隔,最后一个数后为换行符。当该区间没有符合条件的整数时,输出“There is no proper number in the interval.”
程序运行效果:
Sample 1:
1 10000 0↙
6 28 496 8128↙
Sample 2:
2000 5000 4↙
2048 2144 4030 4096↙
Sample 3:
900 1000 0↙
There is no proper number in the interval.↙
#include<stdio.h>
#include<math.h>
int t=0;
void yinshu(int i)//用于求因数
{
int j;
for(j=1;j<i;j++)//这个地方可以优化
{
if((i%j)==0){
//printf("%d\n",j);
t+=j;
}
//printf("%d\n",t);
}
}
int main()
{
int a,b,c,i,sum=0,zgs=0;
scanf("%d%d%d",&a,&b,&c);
for(i=a;i<=b;i++)
{
yinshu(i);
if(fabs(i-t)<c||fabs(i-t)==c)
{
sum++;
if(sum==5)
{
printf("%d\n",i);sum=0;
}
else printf("%d ",i);
zgs++;
}
t=0;
}
if(zgs==0)printf("There is no proper number in the interval.\n");
//printf("%d\n",t);
return 0;
}
这题解题方面问题不大,只是时间方面可以进一步优化,以下是优化并且AC的代码
#include<stdio.h>
#include<math.h>
int t=0;
void yinshu(int i)
{
int j;
/*for(j=1;j<i;j++)//可优化
{
if((i%j)==0){
//printf("%d\n",j);
t+=j;
}
//printf("%d\n",t);
}*/
for(j=1;j<=sqrt(i);j++){//加上等号,i=1时会输出1,与题目不符;不加等号,当i为由两个相同因数相乘时,该因数会被忽略
if((j==1)&&(sqrt(i)==1)){//将i=1的情况单独列出
t=0;break;
}
if((i%j)==0){
//printf("%d\n",j);
if(j==1)t+=j;//在i!=1的情况下,1是要加的
else {
if(j==(i/j))t=t+j;// 由两个相同因数相乘,只计其中一个
else t=t+j+(i/j);
}
}
}
}
int main()
{
int a,b,c,i,sum=0,zgs=0;
scanf("%d%d%d",&a,&b,&c);
for(i=a;i<=b;i++)
{
yinshu(i);
if(fabs(i-t)<c||fabs(i-t)==c)
{
sum++;
if(sum==5)
{
printf("%d\n",i);sum=0;
}
else printf("%d ",i);
zgs++;
}
t=0;
}
if(zgs==0)printf("There is no proper number in the interval.\n");
//printf("%d\n",t);
return 0;
}
嘿嘿嘿
对于这个题,提示我们对递推公式的应用可以减小时间与内存
#include<stdio.h>
#include<math.h>
int main()
{
double x,zhi=0,i,p;//记得赋初值
scanf("%lf",&x);
for(i=0;;i++)
{
if(i==0)p=1;
else p*=(x/i);//根据两项之间的乘除运算,找出递推关系
zhi+=p;
if(fabs(p)<1e-8)break;
}
printf("%.4lf\n",zhi);
//printf("%.4lf\n",exp(x));
return 0;
}
经典的哥德巴赫猜想
B. 实验4_2_哥德巴赫猜想
运行时间限制: 1000 运行内存限制: 65536
作者: bupt_admin 是否specialjudge: False
题目描述
问题描述:
哥德巴赫猜想中写到,一个充分大的偶数(大于等于4),它可以分解为两个素数之和。你的任务是用计算机简单验证哥德巴赫猜想,已知一个偶数n(大于等于4),将它分解为两个素数的所有可能情况打印出来。
输入与输出要求:
输入一个偶数n(4≤n≤10000),代表待验证的偶数。输出偶数分解为两个素数之和的所有可能情况,每种情况占一行。
程序运行效果:
Sample 1:
66↙
5 and 61
7 and 59
13 and 53
19 and 47
23 and 43
29 and 37↙
Sample 2:
200↙
3 and 197
7 and 193
19 and 181
37 and 163
43 and 157
61 and 139
73 and 127
97 and 103↙
我首先研究了一下合数的判断方法
#include<stdio.h>
#include<math.h>
int main(){
//int l,k,t=0;
int k;
scanf("%d",&k);
/*for(l=2;l<k;l++)
{
if(k%l==0){
printf("N\n");break;
}
else t++;
}
printf("%d\n",t);
return 0;*/
int l;
1 for(l=2;l<=sqrt(k);l++)//一个数如果为合数,必有一个小于平方根和一个大于平方根的因数
{
if(k%l==0){
printf("heshu\n");continue;
}
else printf("%d\n",l);
}
int i;
2 for(i=2;i<k;i++)//一个数如果为合数,必有一个小于平方根和一个大于平方根的因数
{
if(k%i==0){
printf("heshu\n");continue;
}
else printf("%d\n",i);
}
return 0;
}
很显然,1要比2花费的时间少,这个题使用函数的话,还有一个要注意的地方,关于函数的返回值问题
#include<stdio.h>
#include<math.h>
int sushu(int k)
{
int l;
for(l=2;l<sqrt(k);l++)//一个数如果为合数,必有一个小于平方根和一个大于平方根的因数
{
if(k%l==0){
return 0;break;
}
//else printf("Y\n");
}
//return 1;
}
int main()
{
int n,i,j;
scanf("%d",&n);
for(i=2;i<=(n/2);i++)
{
j=n-i;
printf("%d %d\n",sushu(i),sushu(j));//函数如果有返回值,返回的是接受的数经过运算的结果
if(sushu(i)==0||sushu(j)==0)continue;//如果不给返回值,不能直接用函数==具体数值
else printf("%d and %d\n",i,j);
}
return 0;
}
E. 实验3_11_最大公约数和最小公倍数
运行时间限制: 1000 运行内存限制: 65536
作者: scshuanghai 是否specialjudge: False
题目描述
已知两个正整数m和n,求其最大公约数和最小公倍数。
输入与输出要求:
输入的正整数m和n之间用空格分隔。输出的最大公约数和最小公倍数之间用空格分隔。测试用例保证m、n及其最小公倍数可以用int存储。
程序运行效果:
Sample 1:
12 36↙
12 36↙
Sample 2:
13 7↙
1 91↙
这题思路不难,只是最后老是答案错误,问了一个同学之后才知道,两个数直接相乘很容易溢出,所以要先除再乘
#include<stdio.h>
#include<math.h>
int main()
{
int m,n,t,i,s=1,j,t2,t1;
scanf("%d%d",&m,&n);
/*if(m<n){
t=n;n=m;m=t;
}*/
if(m<n)t=n,n=m,m=t;//有时可以这样,但break,continue这类语句只能单独一个分号
t1=m;
t2=n;
j=m%n;
while(j!=0){//辗转相除法求最大公约数
m=n;
n=j;
j=m%n;
}
printf("%d %d\n",n,t1/n*t2);//此处用t1*t2/n,在t1*t2处可能就溢出了
return 0;
}
在写出AC代码前,我试了以下错误代码
#include<stdio.h>
#include<math.h>
int main()
{
int m,n,t,i,s=1,j,t2,t1;
scanf("%d%d",&m,&n);
if(m<n)t=n,n=m,m=t;//有时可以这样,但break,continue这类语句只能单独一个分号
if(m%n==0)printf("%d ",n);
else{
for(i=n;i>=1;i--){//用循环求最大公约数,在数字较大的时候容易超时
if((n%i==0)&&(m%i==0)){
printf("%d ",i);break;
}
}
}
t1=m;
t2=n;
if(m%n==0)printf("%d\n",m);
else{//用短除法的原理求最小公倍数,首先要找到公约数,将其约成两个没有公约数的数
//for(i=1;i<=(int)(sqrt(m));i++){//可能是这里的条件问题 ,限定范围在最大数的平方根没有包完全部解空间 ,譬如,36与48,用根号48,也就是6,从1循环到6不能找到其最大公倍数12
for(i=2;i<n;i++){
if((m%i==0)&&(n%i==0)){
m/=i;n/=i;//m,n重新换了之后应重新找公约数来除
s*=i;
}
}
//printf("%d\n",s*m*n);//这步没考虑到m,n同时也会变化
}
//printf("%d %d\n",t2,n);//这步用于检验,可忽略
printf("%d\n",(t1*t2)/n);
return 0;
}
前面用循环求最大公约数没毛病,考虑求最小公倍数用短除法写一下:中心思想为,找出两数的公约数,约掉,直到两数没有公约数。以下是新鲜出炉的短除法代码。
#include<stdio.h>
int main()
{
int m,n,i,s=1,t;
scanf("%d%d",&m,&n);
if(m<n)t=n,n=m,m=t;
if(m%n==0)printf("%d\n",m);
else{
for(i=2;i<=n;i++)
{
//printf("%d\n",n);
if(m%i==0&&n%i==0){
s*=i;
m/=i;
n/=i;
i=1;//!!此处不能为2,for循环循环一次才执行最后一句,即若此处为i=2,最后会得到i=3开始下一次循环
//printf("%d %d\n",m,n);
}
}
printf("%d\n",s*m*n);
}
return 0;
}
经过oj的检验,它没毛病。
简单的数字拆分
A. 实验2_7_数字拆分
运行时间限制: 1000 运行内存限制: 65536
作者: bupt_admin 是否specialjudge: False
题目描述
问题描述:
已知一个正整数n,n的范围是1—999999999。你的任务是把这个整数分解为单个数字,然后从左至右依次打印出每一个数字。例如将整数“12345”分解,得到“1 2 3 4 5”。
输入与输出要求:
输入包括一个正整数,即待拆分的整数n,1<=n<=999999999。输出整数的拆分结果,相邻两个数字之间有一个空格,最后一个数字后是换行符。例如12345的拆分结果为“1 2 3 4 5”
程序运行效果:
Sample 1:
12345↙
1 2 3 4 5↙
Sample 2:
1↙
1↙
贴上我愚蠢的做法先
#include<stdio.h>
int main()
{
int n,a,b,c,d,e,f,g,h,i;
scanf("%d",&n);
a=n/100000000;
b=(n/10000000)%10;
c=(n/1000000)%10;
d=(n/100000)%10;
e=(n/10000)%10;
f=(n/1000)%10;
g=(n/100)%10;
h=(n/10)%10;
i=n%10;
if(a!=0)printf("%d %d %d %d %d %d %d %d %d\n",a,b,c,d,e,f,g,h,i);
else{
if(b!=0)printf("%d %d %d %d %d %d %d %d\n",b,c,d,e,f,g,h,i);
else{
if(c!=0)printf("%d %d %d %d %d %d %d\n",c,d,e,f,g,h,i);
else{
if(d!=0)printf("%d %d %d %d %d %d\n",d,e,f,g,h,i);
else{
if(e!=0)printf("%d %d %d %d %d\n",e,f,g,h,i);
else{
if(f!=0)printf("%d %d %d %d\n",f,g,h,i);
else{
if(g!=0)printf("%d %d %d\n",g,h,i);
else{
if(h!=0)printf("%d %d\n",h,i);
else{
if(i!=0)printf("%d\n",i);
}
}
}
}
}
}
}
}
return 0;
}
别说,还挺好看
这样是挺麻烦的,写代码上,复制粘贴到手软,思维上,也显得不深刻。
以下是经过修改后的代码
#include<stdio.h>
int main()
{
int n,len=1,t,i,s=1;
scanf("%d",&n);
t=n;
while((n/10)!=0)//用于计算n的位数
{
len++;
s*=10;
n/=10;
}
for(i=1;i<=len;i++)
{
if(i==len)printf("%d\n",t/s);
else printf("%d ",t/s);
t=t%s;
s/=10;
}
return 0;
}
最后,再附上我的一些发现
#include<stdio.h>
#include<math.h>
int main()
{
printf("%d\n",(int)(sqrt(6)));//不加强制转换,输出的是一些毫无关联的整数
printf("%f\n",sqrt(6));
printf("%d\n",sqrt(6));
return 0;
}
运行结果是这样的
没了,嘿嘿