跳转至

筛法

Eratosthenes 筛法

std::vector<bool> isp;
void eratosthenes(int n = 1e7) {
    isp.resize(n + 1, true);
    isp[0] = isp[1] = false;
    for (int i = 2; (i64)i * i <= n; ++i)
        if (isp[i])
            for (int j = i * i; j <= n; j += i) isp[j] = false;
}
const std::vector<bool> isp = [](int n) {
    std::vector<bool> p(n + 1, true);
    p[0] = p[1] = false;
    for (int i  = 2; (i64)i * i <= n; ++i) {
        if (p[i])
            for (int j = i * i; j <= n; j += i) p[j] = false;
    }
    return p;
}(1e7);

复杂度 \(\Theta(n \log \log n)\) 。本实现采用 std::vector<bool> 优化,多数时候速度优于 Euler 筛法。

Euler 筛法(线性筛法)

std::vector<int> primes{}, spf;
void sieve(int n = 1e7) {
    spf.resize(n + 1);
    for (int i = 2; i <= n; ++i) {
        if (!spf[i]) {
            spf[i] = i;
            primes.push_back(i);
        }
        for (auto j : primes) {
            if (j > spf[i] || j > n / i) break;
            spf[i * j] = j;
        }
    }
}

复杂度 \(\Theta(n)\) 。由于常数影响略慢于 Eratosthenes 筛法,优点是可以求最小质因子以及多种数论函数。