复杂度 \(O(n^\frac 23)\),计算 \(1\sim n\) 的素数个数
#define div(a, b) (1.0 * (a) / (b))
#define half(x) (((x) - 1) / 2)
i64 Meissel_Lehmer(i64 n) {
if (n <= 3) {
return max(n - 1, 0LL);
}
long long v = sqrtl(n);
int s = (v + 1) / 2;
vector<int> smalls(s), roughs(s);
vector<i64> larges(s);
for (int i = 0 ; i < s ; i++) {
smalls[i] = i;
}
for (int i = 0 ; i < s ; i++) {
roughs[i] = i * 2 + 1;
}
for (int i = 0 ; i < s ; i++) {
larges[i] = half(n / roughs[i]);
}
vector<bool> skip(v + 1);
int pc = 0;
for (int p = 3 ; p <= v ; p += 2) {
if (skip[p] == false) {
i64 q = p * p;
if (q * q > n) {
break;
}
skip[p] = true;
for (int i = q ; i <= v ; i += 2 * p) {
skip[i] = true;
}
int ns = 0;
for (int k = 0 ; k < s ; k++) {
int i = roughs[k];
if (skip[i]) {
continue;
}
long long d = 1LL * i * p;
larges[ns] = larges[k] - (d <= v ? larges[smalls[d >> 1] - pc] : smalls[half(div(n, d))]) + pc;
roughs[ns++] = i;
}
s = ns;
for (int i = half(v), j = (((v / p) - 1) | 1) ; j >= p ; j -= 2) {
int c = smalls[j / 2] - pc;
for (int e = j * p / 2 ; i >= e ; i--) {
smalls[i] -= c;
}
}
pc++;
}
}
larges[0] += 1LL * (s + 2 * (pc - 1)) * (s - 1) >> 1;
for (int k = 1 ; k < s ; k++) {
larges[0] -= larges[k];
}
for (int L = 1 ; L < s ; L++) {
int q = roughs[L];
long long m = n / q;
int e = smalls[half(m / q)] - pc;
if (e < L + 1) {
break;
}
long long t = 0;
for (int k = L + 1 ; k <= e ; k++) {
t += smalls[half(div(m, roughs[k]))];
}
larges[0] += t - 1LL * (e - L) * (pc + L - 1);
}
return larges[0] + 1;
}
#undef div
#undef half
标签:smalls,pc,int,roughs,half,++,Meissel,Lehmer,模板
From: https://www.cnblogs.com/Kescholar/p/18351413