素数的求法

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

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;
}
这种算法可以让我们快速的求出任意给定的连续区域内的素数,而且也很容易查找该素数的位置。

相关文档
最新文档