线性筛素数
线性筛素数的基本思想是:每个合数只被筛一次,将被其最大因数筛掉。
假设我们依据flag数组从小到大判断每个数是否是素数,如果当前该数还未被筛掉,那么就是素数,因为在比它小的数中没有发现因数,将素数加入素数表中。对每一个数i(不论素数或合数),用它筛掉flag数组中以它为最大因数的数。因为每个数只去筛以它为最大因数的数,所以每个合数只会被一个数筛,就是它的最大因数,以此达到线性的复杂度。
假设当前的数是i。以i为最大因数的数是哪些呢?这些数必然是i乘上一个比它小的素数(如果该数是i乘上一个比它大的素数,显然i不会是该数的最大因数;如果是i乘上一个合数x = p1*p2*...*pk (pi为素数),显然通过将x的一些素因数与i相乘会得到比i大的因数)。
假设i可以表示为素数乘积:i = p1*p2*...*pn,x是一个比i小的素数(x显然已经被筛出来了,在我们的素数表中),其中i最小的素因数是p1。i只有与当前素数表中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 }
posted on 2012-07-13 10:41 Lattexiaoyu 阅读(580) 评论(2) 编辑 收藏 举报