线性筛素数

  线性筛素数的基本思想是:每个合数只被筛一次,将被其最大因数筛掉

  假设我们依据flag数组从小到大判断每个数是否是素数,如果当前该数还未被筛掉,那么就是素数,因为在比它小的数中没有发现因数,将素数加入素数表中。对每一个数i(不论素数或合数),用它筛掉flag数组中以它为最大因数的数。因为每个数只去筛以它为最大因数的数,所以每个合数只会被一个数筛,就是它的最大因数,以此达到线性的复杂度。

  假设当前的数是i。以i为最大因数的数是哪些呢?这些数必然是i乘上一个比它小的素数(如果该数是i乘上一个比它大的素数,显然i不会是该数的最大因数;如果是i乘上一个合数x = p1*p2*...*pk pi为素数),显然通过将x的一些素因数与i相乘会得到比i大的因数)。

  假设i可以表示为素数乘积:i = p1*p2*...*pnx是一个比i小的素数(x显然已经被筛出来了,在我们的素数表中),其中i最小的素因数是p1i只有与当前素数表中p<=p1的素数相乘,得到的数y才以i为最大因数反证:如果i乘上pm得到y = i*pm,且pm>p1,那么y有因数y/p1 > i = y/pm

  所以对每一个数i,乘上素数表中不大于i的最小素因数p1的素数,将得到的数从flag数组中筛去,我们就可以在线性的时间复杂度下得到一个素数表。

  代码:

 

 1 int flag[10001],p[10001],pnum;
 2 
 3 void createP(){
 4     pnum=0;
 5     for(int i=0; i<=10000; i++){
 6         flag[i]=0;
 7     }
 8     for(int i=2; i<=10000; i++){
 9         if(flag[i]==0){
10             p[pnum++]=i;
11         }
12         for(int j=0; j<pnum && p[j]*i<=10000; j++){
13             flag[p[j]*i]=1;
14             if(i%p[j]==0)
15                 break;
16         }
17     }
18 }

 

 

原文地址:https://www.cnblogs.com/Lattexiaoyu/p/2589788.html