码迷,mamicode.com
首页 > 其他好文 > 详细

关于筛法

时间:2018-10-27 00:14:49      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:情况   void   算法   例子   简单算法   for   span   max   额外   

众所周知,筛法是打素数表的重要方法。基础的筛法也是很容易的,不需要多加赘述。这里提供一个优化的方法。

一般使用的筛法都是埃拉托斯特尼筛法,其代码如下:


void getPrime()  {      

 prime[0]=false;    

 prime[1]=false;     

 for (int i=2;  i<INT_MAX;  i++)        

   if (prime[i]) {         

  primes[++cnt ]=i;    

  for (int k=i*2; k<INT_MAX; k+=i)       

   prime[k]=false;      

   }      

}   

这种筛法简单易懂,但缺点是经常会多筛去合数,最简单的例子就是6,会被2,3分别筛去。当表的规模很大时,这个额外开销是惊人的。

有一些常数级的优化会被应用以减少这种开销,比如特判2后+2进行。改良后的代码如下:

void getPrime()  {      

 prime[0]=false;    

 prime[1]=false;

 prime[2]=true; 

 tot=0;      

 for (int i=3;  i<INT_MAX;  i+=2)  //这里间距改为了2      

   if (prime[i]) {         

  primes[++tot ]=i;    

  for (int k=i*3; k<INT_MAX; k+=2*i)       //这里的优化似乎比较少人做?事实上i的偶数倍显然是应该被剔除的

   prime[k]=false;      

   }      

}   

但这种优化并不能一劳永逸地解决问题。于是我又查到一个更有效的筛法,代码如下:

void getPrime(){
 prime[0]=1;

 prime[1]=1;

 tot=0;
 for(int i=2;i<MAX;i++){
  if(!prime[i])
   primes[tot]=i,tot++;
  for(int j=0;j<tot&&i*primes[j]<MAX;j++){
   prime[i*primes[j]]=1;
   if(i%primes[j]==0) break;
  }
 }
}

有人把它称作欧拉筛法,也有人称为快速线性筛法。它从根本上杜绝了重复筛合数的问题,保证每个合数只会被它最小的质因子筛去。一般情况下这样的效率已经足够了,但我们会发现,对普通筛法的优化在这里还适用。于是继续优化:

 

void getPrime(){
 prime[0]=1;

 

 prime[1]=1;

 

 tot=0;
 primes[tot]=2;
 tot++;
 for(int i=3;i<MAX;i+=2{
  if(!prime[i])
   primes[tot]=i,tot++;
  for(int j=0;j<tot&&i*primes[j]<MAX;j++){
   prime[i*primes[j]]=1;
   if(i%primes[j]==0) break;
  }
 }
}

 

 这样折腾一个简单算法的优化也没谁了......

关于筛法

标签:情况   void   算法   例子   简单算法   for   span   max   额外   

原文地址:https://www.cnblogs.com/wengsy150943/p/9858824.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!