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;
    }
  • 相关阅读:
    二分图最大匹配的K&#246;nig定理及其证明
    HDOJ 2389 Rain on your Parade
    HDOJ 1083 Courses
    HDOJ 2063 过山车
    POJ 1469 COURSES
    UESTC 1817 Complete Building the Houses
    POJ 3464 ACM Computer Factory
    POJ 1459 Power Network
    HDOJ 1532 Drainage Ditches
    HDU 1017 A Mathematical Curiosity
  • 原文地址:https://www.cnblogs.com/justPassBy/p/5884828.html
Copyright © 2011-2022 走看看