找完数

编程输出2-1000中所有的完全数,所谓的完全数是指整数n的所有小于n的正因数之和若等于n本身,则称数n为完全数。例如6的小于6的正因数为1,2,3。而1+2+3=6,则6是一个完全数。

这道题的解题思路就是遍历,首先你要遍历2-1000里的所有数字

for(int i=2;i<1000;i++)

接着遍历1-i中的所有数字,来找i的因子

for(int j=1;j<i;j++)

如果j是i的因子,那么他肯定能整除i或者说i%j=0

if(i%j==0)

如果j是i的因子;就把他加到因子和sum中

sum+=j;

最后,做一个判定,如果因子和sum等于i,那么i就是完全数

if(sum==i){
	printf("%d是完全数\n",i);
}

下面为最简单的没优化的代码:

#include<stdio.h>
main(){
	for(int i=2;i<1000;i++){//遍历2-1000的所有数字 
		int sum=0;
		for(int j=1;j<i;j++){//遍历1+i之间的所有数字
			if(i%j==0)//如果j是i的因子
				sum+=j;//把就j加到和中
		}
		if(sum==i){//如果因子和sum与i相等,i就是完全数
			printf("%d是完全数\n",i);	//输出i是完全数
		}
	}
}

但是上面的代码我们会发现他有太多的不必要的运算,比如找因子的时候,我们没必要遍历到i,只需要遍历到√i就可以了。
因为因数都是成对出现的。比如,100的因数有:1和100,2和50,4和25,5和20,10和10。看出来没有?成对的因数,其中一个必然小于等于100的开平方,另一个大于等于100的开平方。至于严密的数学证明,用小学数学知识就可以搞定,我就不啰嗦了。
所以代码的第二个遍历就从

for(int j=1;j<i;j++)

变成了

for(int j=1;j<sqrt(i);j++)

而加的部分也由

sum+=j;

变成了

sum=sum+j+i/j;

其中j是你找到的因数,i/j是与之相对的另一个因数
这是我们会发现一个问题,比如说9这个数,开平方等于3,按上述代码的话sum=sum+3+3
3被加了两回,这个错误会出现在所有的平方数中,所以,要进行一个判定,如果这个数是完全平方数,就减去一个平方因子。

int t=sqrt(i);
if(t*t==i)
	sum-=t;

如果因数和在加的过程中比i大了,我们也可以不用算后面的和了,因为肯定不是完全数了

if(sum>i)
	break;

根据以上分析,得到优化的代码如下:

#include<stdio.h>
#include<math.h>
main(){
	for(int i=2;i<1000;i++){//遍历2-1000的所有数字 
		int sum=1;
		int t=sqrt(i);
		if(t*t==i)sum-=t;
		for(int j=2;j<=t;j++){
			if(i%j==0)
				sum=sum+j+i/j;
				if(sum>i)
					break;
		}
		
		if(sum==i){
			printf("%d是完全数\n",i);	
		}
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值