使用基础版的 Meissel-Lehmer,但是对于 n 等于 9985922704307 的数据这份代码会比正确答案 345595245977 少一,求助实现哪里有问题。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define ld long double
#define FOR(i,n,m) for(int i=(n);i<=(m);i++)
#define ROF(i,n,m) for(int i=(n);i>=(m);i--)
#define REP(i,n) for(int i=0;i<(n);i++)
#define SZ(v) v.size()
#define PII pair<int, int>
#define FI(v) v.first
#define SE(v) v.second
#define endl '\n'
template < typename A, typename B >
inline bool chmax(A &x, B y) { return (x < y ? (x = y, true) : false); }
template < typename A, typename B >
inline bool chmin(A &x, B y) { return (x > y ? (x = y, true) : false); }
const int N = 0.8e7 + 10;
const int MI = 1.8e6;
const int MJ = 60;
const int N = 0.8e7 + 10;
const int MI = 1.8e6;
const int MJ = 60;
ll n;
int f[MI + 5][MJ + 5], p[N / 10], ip[N], g[N], cnt;
void init() {
FOR(i, 2, N - 1) { // 线性筛
if(!ip[i]) p[++cnt] = i;
for(int j = 1; j <= cnt && p[j] * i < N; j++) {
ip[i * p[j]] = 1;
if(i % p[j] == 0) break;
}
}
FOR(i, 1, N - 1) g[i] = g[i - 1] + !ip[i]; // 1~i 素数个数,包括 1
FOR(i, 1, MI) f[i][0] = i; // 1~i中被前j个质数筛不掉的数
FOR(i, 1, MI) FOR(j, 1, MJ)
f[i][j] = f[i][j - 1] - f[i / p[j]][j - 1]; // dp
}
ll dp(ll i, ll j) { // 递归求解较大的 dp 数组
if(i <= MI && j <= MJ) return f[i][j];
if(!i || !j) return i;
if(i < N && 1ll * p[j] * p[j] >= i) return max(0ll, g[i] - j); // 全部筛掉
return dp(i, j - 1) - dp(i / p[j], j - 1); // 递归
}
ll sq3(ll x) { // 立方根
ll L = 0, R = 1e5, res;
while(L <= R) {
ll mid = L + R >> 1;
if(mid * mid * mid <= x) res = mid, L = mid + 1;
else R = mid - 1;
}
return res;
}
ll pi(ll n) {
if(n < N) return g[n] - 1;
ll sn = sq3(n);
ll m = g[sn];
ll res = dp(n, m) + m - 1; // 用小于等于 n^(1/3) 的质数来筛
for(m++; 1ll * p[m] * p[m] <= n; m++) // 大于 n^(1/3) 的质数来筛
res -= pi(n / p[m]) - pi(p[m]) + 1;
return res;
}
void solve() {
cin >> n;
init();
cout << pi(n) << endl;
}
int main() {
ios :: sync_with_stdio(0);
cin.tie(0); cout.tie(0);
solve();
return 0;
}