<span style="font-size:24px;color:#ff0000;">/*
完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数。
它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身。
例如,第一个完全数是6,它有约数1、2、3、6,除去它本身6外,其余3个数相加,1+2+3=6。
第二个完全数是28,它有约数1、2、4、7、14、28,除去它本身28外,其余5个数相加,1+2+4+7+14=28。
编程求10000以内的完全数。
*/
#include<stdio.h>
#define RANGE 10000 //查找的最大范围
#define STRLENTH 100 //存放真因子的数组的范围
bool Is_perfect_num(int n)
{
int array[STRLENTH];//存放真因子的数组
int count = 0; //真因子的个数
int total = 0; //真因子相加的和
/*将真因子存放于数组中*/
for(int i=1;i<n;++i)
{
if(n%i == 0)
{
array[count++] = i;
// count++;
}
}
/*计算所有真因子的和*/
for(i=0;i<count;++i)
{
total += array[i];
}
// if(total == n)
// return true;//如果是完全数,返回ture否则返回false
// else
// return false;
return (total == n);
}
int main()
{
for(int i=1;i<=RANGE;++i)
{
if(Is_perfect_num(i))
printf("%d\n",i);
}
return 0;
}
</span>
上述代码,效率不高(求约数时,挨个判断1 --> n-1),且浪费存储空间(用到数组)
改进版代码如下:
/*
6: (1,6) (2,3)---->开始重复--->(3,2)
12:(1,12)(2,6)(3,4)---->开始重复--->(4,3)(6,2)
即:
n=a*b(a<=b) 36=6*6---->a,b是n的真因子------>>>>当b>a时开始重复
*/
#include<stdio.h>
#define RANGE 10000 //查找的最大范围
bool Is_perfect_num(int n)
{
int total = 0; //因子(约数)相加的和
int a = 1; //第一对因子(约数)
int b = n;
while(a < b) //未重复
{
if(n%a == 0)
{
total += a+b;//a,b是n的因子,加入到total中
}
a++;//为下一次判断做准备
b = n/a;
}
/*a,b相等的情况,只加一次,所以不能放入上面的while循环中,得单独考虑*/
if(a == b && a*b == n)
{
total += a;
}
/*注意已下return语句,比用if else简洁多了,本身就是个布尔类型*/
return (total-n == n);//求所有真因子的和,所以将本身减去
}
int main()
{
for(int i=1;i<=RANGE;++i)
{
if(Is_perfect_num(i))
printf("%d\n",i);
}
return 0;
}