线性筛-prime,强大O(n)

和朴素的素数筛法一样,flag数组,记录x是否为素数

flag[x]=0,x为合数

falg[x]=1,x为素数

flag[1],无定义

其核心思想是,用x筛除与之差异最小的y,达到时间上O(n)的目的

何为差异最小,呢?

基于唯一分解定理,我们认为,x的素数分解集合(是可重集)

大小记为|x|,如果|x|+1=|y|,我们则认为x,y差异最小

即此时用x筛去y

更重要的一点:

if(i%p[j]==0)break;

什么意思呢?

可以这样理解,此时的break是为了下一次筛(暂时的失败是为了下一次更好的成功)

应为,能被i筛去的,一定能被p[j]筛去,p[j]后面的下一次反正会用到

所以让p[j]和它后面的素数去筛就好了

举一个栗子:

用2,3我们可以筛去4,6,9

像这样:

   1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17

a[0  0  0  1  0  1  0  0  1  0   0   0   0   0   0   0   0 ]

但是

4,只会筛去8,而没有12

因为,12是留给6筛的,所以代码就很简单了

 1 typedef long long ll;
 2 const int MAXP=50000+10;
 3 ll p[MAXP],flag[MAXP],cnt;
 4 void prime(int n){
 5   for(int i=2;i<=n;i++){
 6     if(!flag[i])p[++cnt]=i;
 7     for(int j=1;j<=cnt && i*p[j]<=n;j++){
 8       flag[i*p[j]]=1;
 9       if(i%p[j]==0)break;
10     }
11   }
12 }
13 int main(){
14   prime(100);
15   for(int i=1;i<=cnt;i++)printf("p[%d]=%lld\n",i,p[i]);
16   return 0;
17 }
prime(100)
posted @ 2017-03-11 14:08  墨鳌  阅读(197)  评论(0编辑  收藏  举报