如果一个数恰好等于它的因子(真因数)之和,则称该数为”完全数”;
各个小于它的约数(真约数,列出某数的约数,去掉该数本身,剩下的就是它的真约数)的和等于它本身的自然数叫做完全数(Perfect number),又称完美数或完备数;
例如6的小于6的正因数为1、2、3,而6是一个完全数;
试求出指定区间 [x,y] 内的完全数;
1.说明:
对指定区间中的每一个整数a实施枚举判别,根据完全数的定义,为了判别整数a是不是完全数,用试商法找出a的所有小于a的因数k,显然,1<=k<=a/2;
注意到1是任何整数的因数,先把因数1定下来,即因数和 s 赋初值,然后设置k从2到a/2的循环,用表达式 a%k=0 判别k是否是a的因数,并求出a的因数累加和 s;
最后若满足条件a=s说明a是完全数,进行打印输出,同时把n的因数从1开始由小到大排列成和式;
2.程序设计:
#include<stdio.h>
int main()
{
int k;
long a,s,x,y;
printf("请输入整数x,y:");
scanf("%ld,%ld",&x,&y);
printf("[%ld,%ld]中的完全数有:\n",x,y);
for(a=x;a<=y;a++)
{
s=1;
for(k=2;k<=a/2;k++) /*试商寻求a的因数k*/
if(a%k==0)
s+=k; /*k是a的因数,复制求和*/
if(a==s)
{
printf("%4ld=1",a);
for(k=2;k<=a/2;k++)
if(a%k==0)
printf("+%d",k);
if(a%2==1)
printf("找到奇完全数!");
printf("\n");
}
}
}
3.程序运行示例及其注意事项:
请输入整数x,y:2,1000
[2,1000]中的完全数有:
6=1+2+3
28=1+2+4+7+14
496=1+2+4+8+16+31+62+124+248
注意:上述程序中求正因数k的试商循环中存在大量的无效循环,为了缩减运行时间,可从减少k的循环次数下手。
*2.程序改进:
注意到:
1)、若数a为非平方数,它的大于1小于a的因数成对出现,每一对中的较小因数要小于a的平方根;
2)、若数a恰为整数b的平方,此时b为a的一个因数,而不是一对;
因此,在作赋值b=sqrt(a)之后,k的循环可设置从2到b来完成,大大减少k循环次数,缩减程序的运行时间;
最后,若a为b的平方,注意到因数b加了两次,应把多加的一次的b从s中减去;
#include<stdio.h>
#include<math.h>
int main()
{
int k;
long a,b,s,x,y;
printf("求区间[x,y]中的完全数.");
printf("请输入整数x,y:");
scanf("%ld,%ld",&x,&y);
printf("[%ld,%ld]中的完全数有:\n",x,y);
for(a=x;a<=y;a++)
{
s=1;
b=sqrt(a);
for(k=2;k<=b;k++)
if(a%k==0)
s=s+k+a/k; /*k与a/k是a的因数*/
if(a==b*b)
s=s-b; /*如果a=b^2,去掉一个重复因数b*/
if(a==s)
{
printf("%4ld=1",a);
for(k=2;k<=a/2;k++)
if(a%k==0)
printf("+%d",k);
if(a%2==1)
printf("奇完全数!");
printf("\n");
}
}
}
*3.改进后程序运行示例及其注意事项:
求区间[x,y]中的完全数.请输入整数x,y:1000,100000
[1000,100000]中的完全数有: 8128=1+2+4+8+16+32+64+127+254+508+1016+2032+4064
注意:至今,寻找到的完全数都是偶完全数。是否存在奇完全数,既不能证明,也不能否定。因此在以上程序中如果找到的完全数是奇数(a%2==1)时,作”奇完全数!“的特别标注。