求小于n的素数个数()

求小于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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值