zoukankan      html  css  js  c++  java
  • 给定范围的素数筛选(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));

     
     

     

     

  • 相关阅读:
    免费申请域名
    分享学习linux网站
    二分法
    node 解决存储xss风险报告
    cf987f AND Graph
    loj2587 「APIO2018」铁人两项
    luogu3830 [SHOI2012]随机树
    luogu3343 [ZJOI2015]地震后的幻想乡
    bzoj2560 串珠子
    luogu3317 [SDOI2014]重建
  • 原文地址:https://www.cnblogs.com/vongang/p/2609659.html
Copyright © 2011-2022 走看看