zoukankan      html  css  js  c++  java
  • 求1e11以内的素数

      有两种做法,一种是打表,另一种是直接求。

    打表

    将1e11每隔len(len=2000w)个数字统计一下该区间内素数的个数,比如cnt[1] 表示[1,len]以内有多少个素数,cnt[2]表示[len+1,2*len】以内有多少个素数,依次类推。

    然后维护一下前缀和,sum[i] = cnt[1] + ....+ cnt[i]

    那么给定一个数字n,求[1,n]以内有多少个素数, 那么只要统计一下sum[n/len],然后再统计一下区间[n/len*len+1, n/len*len + n%len],由于这个内最多只有2000w个,那么只要对该区间内的数字进行筛法求素数,然后统计该区间内素数的个数就可以了。

    任意区间内素数的个数

    所以关键是如果求任意区间内素数的个数, 例如要求区间[a, b]内有多少个数字, 因为该区间内任意合数字的最大最小质因数不会超过sqrt(b),所以只要先求出区间[2,sqrt(b)]内的素数表,那么就可以用该素数表去筛去区间[a,b]内的所有合数。

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <string>
    #include <math.h>
    #include <stdlib.h>
    #include <time.h>
    using namespace std;
    typedef long long LL;
    /*
     * 要求区间[a,b]以内的素数, 那么该区间内所有合数的最小质因数绝对不超过sqrt(b),
     * 所以只要求出[2,sqrt(b)]以内的所有素数,然后用这些素数筛去区间[a,b]内的所有合数即可
     * 要开的数组的大小
     * M > b - a
     * N > sqrt(b)
    */
    const int N = 1000000;
    const int M = 10000000;
    
    bool is_prime[N];
    int prime[N], cnt;
    void get_prime(){
        for(int i=3; i<N; ++i)
            is_prime[i] = true;
        cnt = 0;
        prime[cnt++] = 2;
        for(LL i=3; i<N; i+=2){
            if(is_prime[i]){
                prime[cnt++] = i;
                for(LL j=i*i; j<N; j+=2*i){
                    is_prime[j] = false;
                }
            }
        }
    }
    
    bool is_prime2[M];
    int get_prime2(LL l, LL r){
        for(LL i=0; i<=r-l; ++i)
            is_prime2[i] = true;
    
        for(LL i=0; i<cnt && (LL)prime[i]*prime[i]<=r; ++i){
            /* (l+prime[i]-1)/prime[i]*prime[i] 得到最接近l的prime[i]的倍数是多少 */
            for(LL j=max(2LL, (l+prime[i]-1)/prime[i])*prime[i]; j<=r; j+=prime[i]){
                is_prime2[j-l] = false;
            }
        }
        int res = 0;
        //会把0和1当做素数,所以要减去
        if(l==0)
            res -= 2;
        if(l==1)
            res -= 1;
        for(LL i=0; i<=r-l; ++i){
            res += is_prime2[i];
            /* printf("%lld %d
    ", i+l, is_prime2[i]); */
        }
    
        return res;
    }
    int main()
    {
        /* freopen("in.txt","r",stdin); */
        /* freopen("out.txt","w",stdout); */
        get_prime();
        cout << get_prime2(1, 10000000) << endl;
        return 0;
    }
  • 相关阅读:
    Symmetric Tree
    Splunk的安装与使用
    【BZOJ2662】【BeiJing wc2012】冻结 分层图 裸的!
    Android NFC近场通信03----读写MifareClassic卡
    IOS把图片做成圆形效果
    【翻译自mos文章】CRS显示 正在执行的db instance 是offline状态
    远程訪问路由器下的mac os(ssh+vnc)
    POJ 2488 A Knight&#39;s Journey
    python 分词计算文档TF-IDF值并排序
    ExcelReader(解析Excel的工具类)
  • 原文地址:https://www.cnblogs.com/justPassBy/p/5884828.html
Copyright © 2011-2022 走看看