如果一个数恰好等于它的因子之和,则称此数是完全数。例如:6=1+2+3,(包含1,但不包括本身)
首先穷举它的因数,这里优化一下。根据因数的性质,不小于2的自然整数的可能样式:
2x.....x最大因数=C
3x.....x最大因数=C
.............
优化:根据观察,数C的最大因数(不包括本身)一定小于或等于它的一半,即最大因数<=C/2。这个可以减少穷举的次数。
for(i=1;i<=C/2;i++) if(C%i==0) /*则i是C的因数
假如在穷举中需要保存完全数的因数,可以存放在数组中..
/*第一种解法:存因数于数组中*/ #include <iostream> using namespace std; int main() { int a[15]; int i,C,n,s; for(C=2;C<1000;C++) { n=-1; s=C; for(i=1;i<=C/2;i++)/*最大因数<=C/2*/ { if(C%i==0) {
n++;/*统计因数个数*/ s=s-i;/*循环减去因数*/ a[n]=i;/*数组存储因数*/ } } if(s==0) { cout<<"完全数:"<<C<<endl; for(i=0;i<=n;i++)/*打印因数*/ cout<<a[i]<<" "; cout<<endl; } } return 0; }
/*第二种解法*/ /*直接算出结果*/ #include <iostream> using namespace std; int main() { int C,i,m; for(C=2;C<1000;C++) { for(m=0,i=1;i<=C/2;i++) { if(!(C%i))/*是因数*/ m+=i; } if(m==C) cout<<C<<" "; } return 0; }
补充:2016/3/27号,新的优化方法。
根据因数出现的形式来观察,比如100这个数:
100=1*2*4*5*|10|*20*25*50*100,发现100的因数都是成对出现的(左右对称),以100的平方根10为分界线,左边最大的因数,一定不会超过平方根10,所以试商只用小于或等于整数平方根的数即可。(这个也证明了,为什么检测一个数是否为素数,只用小于或等于它的平方根以下的数试商的原因!)
完全数的定义中不包含本身,所以求和时,先将m置为1,当它能被x整除时,再加上它的另一半对称的数即可,即:
如果C%x==0,则m=m+x+C/x,此外,还有一个特别的地方,如果取的平方根恰好是原数的平方根,最后还要减去一次平方根,因为多加了一次!
#include <iostream> #include <cmath> using namespace std; int main() { int C,i,m,v; for(C=2;C<1000;C++) { m=1; v=sqrt(C);/*取平方根限定试商范围*/ for(i=2;i<=v;i++)/*2~sqrt(C)*/ { if(!(C%i))/*是因数*/ { m=m+i+C/i; } } if(C%v==0) { m=m-v; } if(m==C) cout<<C<<" "; } return 0; }