欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

求小于n的素数个数()

程序员文章站 2022-03-13 10:06:24
...

求小于n的素数个数()

//O(n^3/4)
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define rop(i,a,b) for(int i=(a);i<(b);i++)
 
using namespace std;
typedef long long ll;
const int maxn=4e5+10;
ll phi[maxn/10][105], prime[maxn], pre[maxn];
int x;
bool vis[maxn];
unordered_map<ll,ll>mp;
void init(){
    rop(i,2,maxn)
    {
        if(!vis[i]) {
            prime[x++] = i;
            for (int j = 2; j * i < maxn; j++) {
                vis[i * j] = true;
            }
            pre[i]=pre[i-1]+1;
            continue;
        }
        pre[i]=pre[i-1];
    }
 
    rep(i,0,maxn/10-5){
        phi[i][0] = (ll)i;
        rep(j,1,100){
            phi[i][j] = phi[i][j-1] - phi[i/prime[j-1]][j-1];
        }
    }
}
 
ll mpphi(ll m, ll n){
    if(n==0) return m;
    if(prime[n - 1] >= m) return 1;
    if(m<=maxn/10-5 && n<=100) return phi[m][n];
    return mpphi(m, n-1) - mpphi(m/prime[n-1], n-1);
}
 
ll get_ans(ll x){
    if(x < (ll)maxn) return pre[x];
    if(mp.count(x))
        return mp[x];
    ll y = (int)cbrt(x*1.0);
    ll n = pre[y];
    ll ans = mpphi(x, n) + n -1;
    for(ll i=n; prime[i]*prime[i]<=x; i++) ans = ans - get_ans(x/prime[i])+get_ans(prime[i])-1;
    return mp[x]=ans;
}
 
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    init();
    ll n;
    cin>>n;
    ll anss = get_ans(n);
    cout<<anss<<endl;
    return 0;
}

 

//O(n^2/3)
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define rop(i,a,b) for(int i=(a);i<(b);i++)

using namespace std;

typedef long long ll;
const int maxn = 5e6+10;

bool vis[maxn];
int prime[maxn], pi[maxn];
int x;
void oulasai(int n)
{
    rep (i,2,n)
    {
        if(!vis[i]) prime[x++]=i;
       rop (j,0,x)
        {
            if(i*prime[j]>n) break;
            vis[i*prime[j]]=true;
            if(i%prime[j]==0) break;
        }
    }
}

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(){
    oulasai (maxn);
    sz[0] = 1;
    rep (i,0,PM)  phi[i][0] = i;
    rep (i,1,M){
        sz[i] = prime[i] * sz[i - 1];
        rep (j,1,M) 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;
        rep (i,s+1,s2x) 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;
}
int main(){
    init();
    ll n;
    while(~scanf("%lld",&n)){
        printf("%lld\n",lehmer_pi(n));
    }
    return 0;
}