zoukankan      html  css  js  c++  java
  • SCUT

    https://scut.online/p/142

    但是洲阁筛打表还是超时了,打的表不够长吧,在51nod上面要跑5s。要是快10倍得要密1000倍,根本打不出来(时间意义)。
    暴力check要找的质数是不是要的那个。

    #include<bits/stdc++.h>
    typedef long long ll;
    using namespace std;
    
    const int MAXN = 7500000;
    int n;
    
    int f[MAXN + 5], p[MAXN + 5];
    bool np[MAXN + 5];
    
    ll g(ll n, int m) {
        if(!m)
            return n;
        if(m == 1)
            return n - n / 2;
        if(n <= MAXN) {
            if(f[n] <= m)
                return 1;
            if(f[(int)sqrt(n)] <= m)
                return f[n] - m + 1;
        }
        ll res = g(n, m - 1) - g(n / p[m], m - 1);
        return res;
    }
    
    bool pan(ll x) {
        ll y = sqrt(x);
        return f[y] + g(x, f[y]) - 1 >= n;
    }
    
    void init() {
        for(int i = 2; i <= MAXN; ++i) {
            if(!np[i])
                p[++p[0]] = i;
            for(int j = 1, t; j <= p[0] && (t = p[j] * i) <= MAXN; ++j) {
                np[t] = 1;
                if(i % p[j] == 0)
                    break;
            }
        }
        for(int i = 2; i <= MAXN; ++i)
            f[i] = f[i - 1] + (np[i] == 0);
    
    }
    
    ll pcount[] = {
        373587883,
        776531401,
        1190494759,
        1611623773,
        2038074743,
        2468776129,
        2902958801,
        3340200037,
        3780008329,
        4222234741,
        4666527007,
        5112733757,
        5560695863,
        6010236857,
        6461335109,
        6913774603,
        7367575799,
        7822624247,
        8278737359,
        8736028057,
        9194418049,
        9653704481,
        10113958157,
        10575209467,
        11037271757,
        11500205947,
        11963902331,
        12428375423,
        12893587657,
        13359555403,
        13826206699,
        14293566641,
        14761538761,
        15230122499,
        15699342107,
        16169207209,
        16639648327,
        17110593779,
        17582163853,
        18054236957,
        18526876243,
        18999999247,
        19473535801,
        19947663787,
        20422213579,
        20897216723,
        21372698029,
        21848603809,
        22325014259,
        22801763489
    };
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
        //freopen("Yinku.out", "w", stdout);
    #endif // Yinku
        init();
        while(~scanf("%d", &n)) {
            int px = n / (int)(2e7);
            ll l = px == 0 ? 1 : pcount[px - 1], r = pcount[px], mid;
            //cout << "l=" << l << " r=" << r << endl;
            while(l < r) {
                mid = (l + r) / 2;
                if(pan(mid))
                    r = mid;
                else
                    l = mid + 1;
            }
            printf("%lld
    ", l);
        }
    }
    

    下面的好迷惑啊;

    #include<iostream>
    #include<cmath>
    #include<assert.h>
    using namespace std;
    typedef long long LINT;
    LINT a,b,goal,n;
    int mark[160000],prime[160000],e,bl[10000005];
    LINT pn(int n)
    {
        LINT s=LINT(n*(log(n)+log(log(n))-1)+n*(log(log(n))-2)/log(n)-6.0*n/1000.0);
        return s<=1?1:s;
    }
    
    inline LINT V2IDX(LINT v, LINT N, LINT Ndr, LINT nv) {
        return v >= Ndr ? (N/v - 1) : (nv - v);
    }
    
    LINT primesum(LINT N) {
        LINT *S;
        LINT *V;
    
        LINT r = (LINT)sqrt(N);
        LINT Ndr = N/r;
    
        assert(r*r <= N and (r+1)*(r+1) > N);
    
        LINT nv = r + Ndr - 1;
    
        V = new LINT[nv];
        S = new LINT[nv];
    
        for (LINT i=0; i<r; i++) {
            V[i] = N/(i+1);
        }
        for (LINT i=r; i<nv; i++) {
            V[i] = V[i-1] - 1;
    
        }
    
        for (LINT i=0; i<nv; i++) {
          //S[i] = V[i] * (V[i] + 1) / 2 - 1;若求素数和,使用此处
            S[i]=V[i] - 1;
          //若求素数个数使用此处
        }
    
        for (LINT p=2; p<=r; p++) {
            if (S[nv-p] > S[nv-p+1]) {
                LINT sp = S[nv-p+1];
                LINT p2 = p*p;
                for (LINT i=0; i<nv; i++) {
                    if (V[i] >= p2) {
                    //S[i] -= p* (S[V2IDX(V[i]/p, N, Ndr, nv)] - sp);若求素数和,使用此处
                        S[i] -= 1* (S[V2IDX(V[i]/p, N, Ndr, nv)] - sp);
                      //若求素数个数,使用此处
                    } else {
                        break;
                    }
                }
            }
        }
    
        return S[0];
    }
    
    int main()
    {
        cin>>n;
        a=pn(n);
        if(a%2&&a>1)a=a-1;//防止预估值本身就是素数的情况,刚开始被这里坑了3个test
        b=a+7000000;
        goal=n-primesum(a);
        for(int i=2;i<=160000;i++)
        {
            if(!mark[i])
            {
                prime[++e]=i;
                for(LINT j=(LINT)i*i;j<=160000;j+=i)
                {
                    mark[j]=1;
                }
            }
        }
        LINT xxx,c;
        for(int i=1;i<=e;i++)
        {
            xxx=(LINT)ceil(1.0*a/prime[i]);
            if(xxx==1) xxx++;
            for(LINT j=xxx;(c=j*prime[i])<b;j++)
            {
                bl[c-a]=1;
            }
        }
        int ans=0;
        c=b-a;
        if(a==1) ans--;
        for(int i=0;i<c;i++)
        {
            if(!bl[i]) ans++;
            if(ans==goal)
            {
                cout<<i+a<<endl;
                break;
            }
        }
        return 0;
    }
    

    Meisell-Lehmer算法 计算2~n之间的素数的个数然后二分就可以了。

    bool np[maxn];  
    int prime[maxn],pi[maxn];  
      
    int getprime()  
    {  
        int cnt=0;  
        np[0]=np[1]=true;  
        pi[0]=pi[1]=0;  
        for(int i=2; i<maxn; ++i)  
        {  
            if(!np[i]) prime[++cnt]=i;  
            pi[i]=cnt;  
            for(int j=1; j<=cnt&&i*prime[j]<maxn; ++j)  
            {  
                np[i*prime[j]]=true;  
                if(i%prime[j]==0) break;  
            }  
        }  
        return cnt;  
    }  
    const int M=7;  
    const int PM=2*3*5*7*11*13*17;  
    int phi[PM+1][M+1],sz[M+1];  
    void init()  
    {  
        getprime();  
        sz[0]=1;  
        for(int i=0; i<=PM; ++i) phi[i][0]=i;  
        for(int i=1; i<=M; ++i)  
        {  
            sz[i]=prime[i]*sz[i-1];  
            for(int j=1; j<=PM; ++j)  
            {  
                phi[j][i]=phi[j][i-1]-phi[j/prime[i]][i-1];  
            }  
        }  
    }  
    int sqrt2(ll x)  
    {  
        ll r=(ll)sqrt(x-0.1);  
        while(r*r<=x) ++r;  
        return int(r-1);  
    }  
    int sqrt3(ll x)  
    {  
        ll r=(ll)cbrt(x-0.1);  
        while(r*r*r<=x) ++r;  
        return int(r-1);  
    }  
    ll getphi(ll x,int s)  
    {  
        if(s==0) return x;  
        if(s<=M) return phi[x%sz[s]][s]+(x/sz[s])*phi[sz[s]][s];  
        if(x<=prime[s]*prime[s]) return pi[x]-s+1;  
        if(x<=prime[s]*prime[s]*prime[s]&&x<maxn)  
        {  
            int s2x=pi[sqrt2(x)];  
            ll ans=pi[x]-(s2x+s-2)*(s2x-s+1)/2;  
            for(int i=s+1; i<=s2x; ++i)  
            {  
                ans+=pi[x/prime[i]];  
            }  
            return ans;  
        }  
        return getphi(x,s-1)-getphi(x/prime[s],s-1);  
    }  
    ll getpi(ll x)  
    {  
        if(x<maxn) return pi[x];  
        ll ans=getphi(x,pi[sqrt3(x)])+pi[sqrt3(x)]-1;  
        for(int i=pi[sqrt3(x)]+1,ed=pi[sqrt2(x)]; i<=ed; ++i)  
        {  
            ans-=getpi(x/prime[i])-i+1;  
        }  
        return ans;  
    }  
    ll lehmer_pi(ll x)  
    {  
        if(x<maxn) return pi[x];  
        int a=(int)lehmer_pi(sqrt2(sqrt2(x)));  
        int b=(int)lehmer_pi(sqrt2(x));  
        int c=(int)lehmer_pi(sqrt3(x));  
        ll sum=getphi(x,a)+ll(b+a-2)*(b-a+1)/2;  
        for(int i=a+1; i<=b; i++)  
        {  
            ll w=x/prime[i];  
            sum-=lehmer_pi(w);  
            if(i>c) continue;  
            ll lim=lehmer_pi(sqrt2(w));  
            for(int j=i; j<=lim; j++)  
            {  
                sum-=lehmer_pi(w/prime[j])-(j-1);  
            }  
        }  
        return sum;  
    } 
    
  • 相关阅读:
    常用知识点集合
    LeetCode 66 Plus One
    LeetCode 88 Merge Sorted Array
    LeetCode 27 Remove Element
    LeetCode 26 Remove Duplicates from Sorted Array
    LeetCode 448 Find All Numbers Disappeared in an Array
    LeetCode 219 Contains Duplicate II
    LeetCode 118 Pascal's Triangle
    LeetCode 119 Pascal's Triangle II
    LeetCode 1 Two Sum
  • 原文地址:https://www.cnblogs.com/Yinku/p/11298017.html
Copyright © 2011-2022 走看看