【项目1-完数】
一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6=1+2+3,再如8的因子和是7(即1+2+4),8不是完数。
(1)输入一个数n,判断n是否是完数
[参考解答]
一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6=1+2+3,再如8的因子和是7(即1+2+4),8不是完数。
(1)输入一个数n,判断n是否是完数
[参考解答]
解1:
#include <stdio.h>
int main( )
{
int n,s,m;
printf("输入n:");
scanf("%d", &n);
s=1; //s代表因子和。1是任何数的因子,所以初值s=1,要判断m是否是n的因子,m的取值范围为2到m-1
for(m=2; m<n; m++)
{
if(n%m==0)
s+=m;
}
if(n==s)
{
printf("Yes\n");
//额外增加一个功能,列出这些因子
printf("完数构成: %d = 1 ", n);
for(m=2; m<n; m++)
{
if(n%m==0)
printf("+ %d ", m);
}
}
else
{
printf("No");
}
printf("\n");
return 0;
}
解2(改进版——提高效率)
#include <stdio.h>
#include <math.h>
int main( )
{
int n,s,m;
printf("输入n:");
scanf("%d", &n);
s=1;
//下面的循环次数较解法1少了很多(n越大,效果越明显),充分利用了因子的对称性
for(m=2; m<sqrt(n); m++) //思考:若s初值为1,m从1开始,结果会怎样?
{
if(n%m==0) //若m是n的因子,则n/m也是n的因子,一旦判断m是n的因子,一次将两个数都累加起来
s+=(m+n/m); //例:n=56时,判断出56%2==0为真,则将2及与其对应的因子28一次累加到s上,m到7即可结束循环
}
if(m*m==n) //若恰好n是某数的平方,上面的循环中没有考虑,现在补上。当然,m只能被累加一次
s+=m;
//printf("因子和:%d", s); //测试时可以加上这一句看看
if(n==s)
{
printf("Yes\n");
}
else
{
printf("No");
}
printf("\n");
return 0;
}
(2)输出1000以内的所有完数
[参考解答]
有了上面的工作,很容易做一个双重循环,解决这个问题。
#include <stdio.h>
#include <math.h>
int main( )
{
int n,s,m;
printf("1000之间的完数有:");
for(n=2; n<=1000; ++n)
{
s=1;
for(m=2; m<sqrt(n); m++)
{
if(n%m==0)
s+=(m+n/m);
}
if(m*m==n)
s+=m;
if(n==s)
printf("%d ", n);
}
printf("\n");
return 0;
}
(3)亲密数:如果整数A的全部因子(包括1,不包括A本身)之和等于B;且整数B的全部因子(包括1,不包括B本身)之和等于A,则将整数A和B称为亲密数。求3000以内的全部亲密数。(提示:按照亲密数定义,要判断数a是否有亲密数,只要计算出a的全部因子的累加和为b,再计算b的全部因子的累加和为n,若n等于a则可判定a和b是亲密数。)
[参考解答]
[参考解答]
#include <stdio.h>
int main()
{
int i,a,b,n;
for(a=1;a<=3000;++a)
{
//计算a的所有因子的和b
b=0;
for(i=1;i<a;++i)
{
if(a%i==0)
b+=i;
}
//计算b的所有因子的和n
n=0;
for(i=1; i<b; ++i)
{
if(b%i==0)
n+=i;
}
if(a==n) //a与其因子和的因子和相等
{
printf("a= %d, 其因子和b=%d\n", a, b);
}
}
printf("\n");
return 0;
}