给定范围的素数筛选(POJ 2689)

问题:求L 到 R范围内的所有素数 (L < R <= 2147483647, R - L <= 10^6)

解:要判断x是否是素数,可以看 x %(所有比x小的素数)是否有0出现。。。

当然,还可以优化一下 x % (所有比sqrt(x)小的素数)

已知 sqrt(2147483647) = 49361;

打出 [2, 49361]范围内的素数表,大约不到5000个素数。

然后用小于 sqrt(R)的素数乘上一个系数进行枚举,这样乘出来的数必然不是素数。把所有这些数筛小,剩下的就是素数了。

至于这个系数怎么确定?可以知道这个系数的下限为 K = L/prime[i],当然,如果prime[i] >= L的话,K初始为2。其实就是K*prime[i]要保证大于L且离L最近

 

打表:

    CL(vis, true);
    for(LL i = 2; i < N; ++i) {
        for(LL j = LL(i)*LL(i); j < N; j += i)  vis[j] = false;
    }
    n = 0;
    for(LL i = 2; i < N; ++i) {
        if(vis[i])  {
            prime[n++] = i;
        }
    }

 

 

筛掉非素数:

void get_p2(LL l, LL r) {
    LL i;
    LL k;
    if(r < N) {    //如果r <= 49361,直接用原来的素数表就可以
        i = 0;
        while(prime[i] < l) ++i;
        for(n2 = 0; prime[i] <= r; ++i)
            p2[n2++] = prime[i];
        return ;
    }
    CL(vis, true);
    for(i = 0; i < n && prime[i]*prime[i] <= r; ++i) {
        if(prime[i] >= l)   k = 2;
        else {
            k = l/prime[i];
            if(k*prime[i] < l)  ++k;
        }
        while(k*prime[i] <= r) {
            vis[k*prime[i] - l] = false;
            //printf("%lld %lld %d\n", k*prime[i], k*prime[i] - l, prime[i]);
            ++k;
        }
    }
    n2 = 0;
    for(i = 0; i <= r - l; ++i) {
        if(vis[i])  p2[n2++] = i + l;
    }
}

 

设原素数表有n个素数,k增长次数的平均数为ave(k),时间复杂度为O(n*ave(k));

 
 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2012-07-26 11:03  AC_Von  阅读(342)  评论(0编辑  收藏  举报