Meissel_Lehmer模板

复杂度 \(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
posted @ 2024-08-09 20:01  Ke_scholar  阅读(12)  评论(0编辑  收藏  举报