zoukankan      html  css  js  c++  java
  • 爆炸快求1~n有多少素数

    这个求一千亿以内的素数大约用6780ms

    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    #include <stdlib.h>
    #include <time.h>
    #include <math.h>
    using namespace std;
    __int64  *primarr, *v;
    __int64  q = 1, p = 1;
    
    void Out(__int64 a)    //输出外挂
    {
        if(a>9)
            Out(a/10);
        putchar(a%10+'0');
    }
    
    __int64 Scan()     //输入外挂
    {
        __int64 res=0,ch,flag=0;
        if((ch=getchar())=='-')
            flag=1;
        else if(ch>='0'&&ch<='9')
            res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')
            res=res*10+ch-'0';
        return flag?-res:res;
    }
    //π(n)
    __int64  pi(__int64  n, __int64  primarr[], __int64  len)
    {
        __int64  i = 0, mark = 0;
        for (i = len - 1; i > 0; i--) {
            if (primarr[i] < n) {
                mark = 1;
                break;
            }
        }
        if (mark)
            return i + 1;
        return 0;
    }
    //Φ(x,a)
    __int64  phi(__int64  x, __int64  a, __int64  m)
    {
        if (a == m)
            return (x / q) * p + v[x % q];
        if (x < primarr[a - 1])
            return 1;
        return phi(x, a - 1, m) - phi(x / primarr[a - 1], a - 1, m);
    }
    __int64  prime(__int64  n)
    {
        char *mark;
        __int64  mark_len;
        __int64  count = 0;
        __int64  i, j, m = 7;
        __int64  sum = 0, s = 0;
        __int64  len, len2, len3;
    
        mark_len = (n < 10000) ? 10002 : ((__int64 )exp(2.0 / 3 * log(n)) + 1);
    
        //筛选n^(2/3)或n内的素数
        mark = (char *)malloc(sizeof(char) * mark_len);
        memset(mark, 0, sizeof(char) * mark_len);
        for (i = 2; i < (__int64 )sqrt(mark_len); i++) {
            if (mark[i])
                continue;
            for (j = i + i; j < mark_len; j += i)
                mark[j] = 1;
        }
        mark[0] = mark[1] = 1;
    
        //统计素数数目
        for (i = 0; i < mark_len; i++)
            if (!mark[i])
                count++;
    
        //保存素数
        primarr = (__int64  *)malloc(sizeof(__int64 ) * count);
        j = 0;
        for (i = 0; i < mark_len; i++)
            if (!mark[i])
                primarr[j++] = i;
    
        if (n < 10000)
            return pi(n, primarr, count);
    
        //n^(1/3)内的素数数目
        len = pi((__int64 )exp(1.0 / 3 * log(n)), primarr, count);
        //n^(1/2)内的素数数目
        len2 = pi((__int64 )sqrt(n), primarr, count);
        //n^(2/3)内的素数数目
        len3 = pi(mark_len - 1, primarr, count);
    
        //乘积个数
        j = mark_len - 2;
        for (i = (__int64 )exp(1.0 / 3 * log(n)); i <= (__int64 )sqrt(n); i++) {
            if (!mark[i]) {
                while (i * j > n) {
                    if (!mark[j])
                        s++;
                    j--;
                }
                sum += s;
            }
        }
        free(mark);
        sum = (len2 - len) * len3 - sum;
        sum += (len * (len - 1) - len2 * (len2 - 1)) / 2;
    
        //欧拉函数
        if (m > len)
            m = len;
        for (i = 0; i < m; i++) {
            q *= primarr[i];
            p *= primarr[i] - 1;
        }
        v = (__int64  *)malloc(sizeof(__int64 ) * q);
        for (i = 0; i < q; i++)
            v[i] = i;
        for (i = 0; i < m; i++)
            for (j = q - 1; j >= 0; j--)
                v[j] -= v[j / primarr[i]];
    
        sum = phi(n, len, m) - sum + len - 1;
        free(primarr);
        free(v);
        return sum;
    }
    
    int main()
    {
        __int64  n;
        //int h;
        ///clock_t start, end;
        //freopen("C:\Users\acer\Desktop\in.txt","r",stdin);
        //std::ios::sync_with_stdio(false);
        while(~scanf("%lld",&n))
        {
            if(n==2)
            {
                printf("1
    ");
                continue;
            }
            //p=1;
            //q=1;
            //start = clock();
            Out(prime(n+1));
            printf("
    ");
            //end = clock() - start;
            //printf("用时%lfms
    ",(double)end);
        }
        return 0;
    }

    这个完全就是爆炸了

    #include <bits/stdtr1c++.h>
    
    #define MAXN 100    // pre-calc max n for phi(m, n)
    #define MAXM 100010 // pre-calc max m for phi(m, n)
    #define MAXP 666666 // max primes counter
    #define MAX 10000010    // max prime
    #define clr(ar) memset(ar, 0, sizeof(ar))
    #define read() freopen("lol.txt", "r", stdin)
    #define dbg(x) cout << #x << " = " << x << endl
    // compressed bool flag for sieve prime. (i >> 1) because even numbers are omitted.
    #define setbit(ar, i) (((ar[(i) >> 6]) |= (1 << (((i) >> 1) & 31))))
    #define chkbit(ar, i) (((ar[(i) >> 6]) & (1 << (((i) >> 1) & 31))))
    #define isprime(x) (( (x) && ((x)&1) && (!chkbit(ar, (x)))) || ((x) == 2))
    
    using namespace std;
    
    namespace pcf{
        long long dp[MAXN][MAXM];
        unsigned int ar[(MAX >> 6) + 5] = {0};
        int len = 0, primes[MAXP], counter[MAX];
    
        void Sieve(){
            setbit(ar, 0), setbit(ar, 1);
            for (int i = 3; (i * i) < MAX; i++, i++){
                if (!chkbit(ar, i)){
                    int k = i << 1;
                    for (int j = (i * i); j < MAX; j += k) setbit(ar, j);
                }
            }
    
            for (int i = 1; i < MAX; i++){
                counter[i] = counter[i - 1];
                if (isprime(i)) primes[len++] = i, counter[i]++;
            }
        }
    
        void init(){
            Sieve();
            for (int n = 0; n < MAXN; n++){
                for (int m = 0; m < MAXM; m++){
                    if (!n) dp[n][m] = m;
                    else dp[n][m] = dp[n - 1][m] - dp[n - 1][m / primes[n - 1]];
                }
            }
        }
    
        long long phi(long long m, int n){
            if (n == 0) return m;
            if (primes[n - 1] >= m) return 1;
            if (m < MAXM && n < MAXN) return dp[n][m];
            return phi(m, n - 1) - phi(m / primes[n - 1], n - 1);
        }
    
        long long Lehmer(long long m){
            if (m < MAX) return counter[m];
    
            long long w, res = 0;
            int i, a, s, c, x, y;
            s = sqrt(0.9 + m), y = c = cbrt(0.9 + m);
            a = counter[y], res = phi(m, a) + a - 1;
            for (i = a; primes[i] <= s; i++) res = res - Lehmer(m / primes[i]) + Lehmer(primes[i]) - 1;
            return res;
        }
    }
    
    
    
    int main(){
        pcf::init();
        long long n, res;
    
        while (scanf("%lld", &n) != EOF){
            printf("%lld
    ", pcf::Lehmer(n));
        }
        return 0;
    }

      

  • 相关阅读:
    racktable安装过程
    racktables
    EM上的按钮是方框的问题
    install oracle
    记一次ORACLE无法启动登陆事故
    安装rlwrap-0.37.tar.gz
    centos7 安装oracle 11g数据库
    centos 7 安装mariadb
    centos7 lamp
    Linux安全之SSH 密钥创建及密钥登录
  • 原文地址:https://www.cnblogs.com/wuwangchuxin0924/p/5886868.html
Copyright © 2011-2022 走看看