1. 素数:一个只有两个因子(1和本身)的大于1自然数,最小的素数为2;
2. 按定义来判断某个数n是否为素数。
1. 解题思路:判断在2-sqrt(n)的范围内是否有n的因子。如果有,则该数不为素数(即合数);否则该数就为素数。
2. 代码:
#include
using namespace std;
bool isPrime(int n)
{
bool prime= true;
for(int i=2;i*i<=n;i++)
if(n%i==0) //nhas another divisor except 1 and n
{
prime= false;
break;
}
return prime;
}
int main( )
{
int n;
cin>>n;
if(isPrime(n))
cout<<"yes"<<endl;
else
cout<<"no"<<endl;
return 0;
}
时间效率为:O(sqrt(n));
*但是当要联系判断多个数是否为素数时,这种方法的效率就太低了。下面介绍另外一种效率略高的方法
3.筛选法求素数:
如果要连续判断大量的数是否为素数时,用筛选法是一种不错的方法,但是也有缺点(这点稍后再谈):
在介绍这种方法之前,你必须要明白任何一个素数都可以由多个合数组成。
1. 解题思路:
1.创建一个长度为n的数组,数组的下标就表示相应的数,其内的值表示该数是否为素数(0表示不是素数,1表示是素数)。
2.将下标为0和下标为1的数组内的内容标为0;
3.从2开始,直到p(2<=p<=sqrt(n)),把所有的kp(kp<=n,k=2,3……)都 标记为0(即为合数)。
4.输出数组中值为1的数的下标(即为1-n中所有的素数)
2.代码:
#include
using namespace std;
void isPrime(int *prime,int n)
{
for(int i=2;i*i<=n;i++)
{
if(prime[i]) //从素数开始
{
for(int j=2*i;j<=n;j+=i) //下标为素数的倍数的数为a合数
prime[j]=0;
}
}
}
int main()
{
int prime[101];
for(int i=0;i<101;i++)
{
prime[i]=1;
}
prime[0]=0;
prime[1]=0;
isPrime(prime,100);
for(int i=0;i<101;i++)
if(prime[i]==1) //1表示素数,0表示合数
cout<<i<<endl;
return 0;
}
这种算法的时间复杂度小于n*sqrt(n);
这种方法有一个缺陷:
1. 如果判断1000个数是否为素数,但是这些数分布在(1*10^8,1*10^9)范围内时,会造成极大的空间浪费。
4.下面介绍一种可以节省空间的求素数的算法:
1.解题思路:
1. 定义一个数组,长度大约为你所要求的数的最大范围的1/9,用于存储相应的素数。
2. 从5开始判断某个奇数是否为素数(偶数一定不是素数),如果是则放入数组中。
3. 输出数组中的数,即为所求
2.代码:
#include
using namespace std;
int isPrime(int *prime,int n)
{
int num= 2;
prime[0]=2;
prime[1]=3;
for(int i=5;i<=n;i+=2) //排除所有的偶数,逐个判断某个奇数是否为素数
{
bool status= true;
for(int j=0;prime[j]*prime[j]<=i;j++) //判断i是否为素数
{
if(i%prime[j]==0)
{
status= false;
break;
}
}
if(status) //i为a素数,则放入数组中
prime[num++]=i;
}
return num;
}
int main( )
{
int prime[101];
int num= isPrime(prime,100);
for(int i=0;i
cout<<prime[i]<<endl;
return 0;
}
这种算法节约了大量的空间。在时间复杂度上也比上面那种小。
但是这种算法也有确定,就是不容易确定某个范围内的所有的素数。
5.改进版筛选法:
1.解题思路:
1.对于给点的范围[m,n],以m/p(p=2,3,….sqrt(n))开始,每次加上p,那么(m/p+p)就为合数。这就像是从m/p开始的素数筛选法。(此时我们需要判断的是m<=(m/p+p)<=n这个范围内的数是否为素数)
2.代码:
#include
using namespace std;
void isPrime(int m,int n,int *prime)
{
for(int i=2;i*i<=n;i++)
{
int less= m/i;
less*=i;
for(int j=less;j<=n;j+=i)
if(j>=m&&j!=i) //i!=j可以防止把一些素数判断为合数
prime[j-m]=0;
}
}
int main( )
{
int m,n;
cin>>m>>n; //给定的范围[m,n]
int *prime= new int[n-m+1];
for(int i=0;i
prime[i]=1;
isPrime(m,n,prime);
for(int i=0;i
{
if(prime[i]==1&&(n+i)!=1)
cout<<m+i<<endl;
}
cin>>m;
return 0;
}
这种算法可以让我们快速的求出任意给定的连续区域内的素数,而且也很容易查找该素数的位置。
以上五种方法适合的情况不同,大家要灵活运用。
如果以上有错误,请大家不吝指正。