素数筛法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了素数筛法相关的知识,希望对你有一定的参考价值。

参考:http://blog.csdn.net/once_hnu/article/details/6302283

素数,就是只有1和自身两个约数的正整数。2是最小的素数。根据定义,我们就可以直接判断一个数字n是否是素数。优化后的复杂度是O(n*sqrt(n))。原因的话:http://www.goodgoodstudy.pw/?p=38 ,自己也可以稍作思考。但是,在大规模的数据范围时,这个算法会耗时太多,显得十分低效!

下面介绍第二种较为高效的算法-----筛法。

具体筛法是:先把n个自然数按次序排列起来。1不是质数,也不是合数,要划去。第二个数2是质数留下来,而把2后面所有能被2整除的数都划去。2后面第一个没划去的数是3,把3留下,再把3后面所有能被3整除的数都划去。3后面第一个没划去的数是5,把5留下,再把5后面所有能被5整除的数都划去。这样一直做下去,就会把不超过N的全部合数都筛掉,留下的就是不超过N的全部质数。因为希腊人是把数写在涂腊的板上,每要划去一个数,就在上面记以小点,寻求质数的工作完毕后,这许多小点就像一个筛子,所以就把埃拉托斯特尼的方法叫做“埃拉托斯特尼筛法”,简称“筛法”。

 

#include<cmath>
// 1:这是最原始的筛法 
#include<cstdio>
#define Max 30 
bool prime[Max];  
void IsPrime(){  
     prime[0]=prime[1]=0;prime[2]=1;  
     for(int i=3;i<Max;i++)  
       prime[i]=i%2==0?0:1;  
     int t=(int)sqrt(Max*1.0);  
    for(int i=3;i<=t;i++)  
      if(prime[i])  
        for(int j=i+i;j<Max;j+=i)  
           prime[j]=0;  
}


 
int main()
{
    IsPrime();
    for(int i=1;i<=30;++i)
        printf("%d ",prime[i]);

}

 下面是比较快的筛法

  1. //2:优化后的筛法,手动地模拟原始筛法就可以发现,某个数字可能被不止一次地删去  
  2. //   优化后的筛法就可以避免这种不必要的删去操作 

 

#include<cmath>
#include<cstdio>
#define Max 30 
bool prime[Max];  
void IsPrime(){  
     prime[0]=prime[1]=0;prime[2]=1;  
     for(int i=3;i<Max;i++)  
       prime[i]=i%2==0?0:1;  
     int t=(int)sqrt(Max*1.0);  
    for(int i=3;i<=t;i++)  
      if(prime[i])  
        for(int j=i*i;j<Max;j+=2*i)//优化   
           prime[j]=0;
}
int main()
{
    IsPrime();
    for(int i=1;i<=30;++i)
        printf("%d ",prime[i]);
}

 

以上是关于素数筛法的主要内容,如果未能解决你的问题,请参考以下文章

素数筛法(Eratosthenes筛法)

练习筛法遍历素数(Java)

筛法求素数

Eratosthenes筛法 快速求素数

素数专题——素数筛法

素数筛法讲解