2019秋期计导实验四

一如既往地记录写程序过程中遇到的问题


以下是乱序的问题总结

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;
}

运行结果是这样的
在这里插入图片描述
没了,嘿嘿

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值