我们知道,任何一个自然数的因子中都包含1和它本身,也就是说,任何一个自然数都能被1和它本身所整除,而所有小于它本身的因子称为这个自然数的真因子,例如6的因子包括1、2、3、6,它的真因子则是1、2、3;8的因子包括1、2、4、8,它的真因子则是1、2、4。下面我们给出一个重要的定义:
如果一个自然数的真因子之和等于这个自然数本身,则这个自然数就称为完美数。
例如,6=1+2+3,因此6是完美数,而8不等于1+2+4,因此8不是完美数。
那么对于给定的一个自然数n,如何用计算机程序来判定它是否是完美数呢?
方法一:按照完美数的定义
int perfect1(int n)
{
int i,sum=0;
for(int i=1;i<=n/2;i++)
{
if(n%i==0)
{
sum+=i;
}
}
if(sum==n)
return 1;
return 0;
}
方法二:利用欧几里得完美数公式
欧几里得完美数定理
伟大的古希腊数学家欧几里得提出了著名的完美数判定定理,该定理提供了一种求解完美数的更为高效的方法。该定理是说:
如果整数p和2p-1均为素数,则2p-1(2p-1)是完美数。
这里所谓的素数又称为质数,是指除了1和它本身之外,不能被任何其他数所整除的数就称为素数或质数,例如2,3,5,7,11等都是素数。
接下来我们就根据欧几里得完美数定理,设计一个计算机程序来求出更多更大的完美数。通过该定理来求完美数时,首先要解决的关键问题就是素数的判定。
1、素数的判定
根据素数定义
int isPrime1(double n)
{
double i;
//fmod()函数可以对浮点型数据进行取模运算
for(i=2;i<=(int)sqrt(n);i++)
{
if(fmod(n,i)==0)
{
return 0;
}
}
return 1;
}
根据素数分布求素数
首先看一个关于质数分布的规律:大于等于5的质数一定和6的倍数相邻。例如5和7,11和13,17和19等等;
证明:令x≥1,将大于等于5的自然数表示如下:
··· 6x-1,6x,6x+1,6x+2,6x+3,6x+4,6x+5,6(x+1),6(x+1)+1 ···
int isPrime2(double n)
{
if(n==2||n==3)
return 1;
for(int i=5;i<=(int)sqrt(n);i+=5)
{
if(n%i==0||n%(i+2)==0)
return 0;
}
return 1;
}
埃拉托斯特尼筛法
过程图像:https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
基本思想:每判断一个素数,都将该素数的倍数去掉
int prime[100];
int isPrime3()
{
int cnt=0;
for(int i=2;i<1000;i++)
{
if(!prime[i])
{
prime[cnt++]=i;
for(int j=i+i;j<1000;i+=i)
{
prime[j]=1;
}
}
}
cout<<"1-100以内的素数:"<<endl;
for(int i=0;i<cnt;i++)
{
cout<<prime[i]<<" ";
}
}
接下来就是完美数求解
//当p范围是[2,31]时,完美数有几个
long long perfect2()
{
long long p,t,x,y;
for(p=2;p<=31;p++)
{
if(isPrime1(p)==1)
{
t=1;
for(int k=1;k<=p;k++)
{
t=t*2;
}
x=t/2;
y=t-1;
if(isPrime1(y)==1)
{
cout<<x*y<<endl;
}
}
}
}
作者很懒,完美数涉及到的欧几里得,还有很多知识,感兴趣的可以看一些数论知识,你还会发现更神奇的数学!!!