数学

埃氏筛

埃拉托色尼筛(Sieve of Eratosthenes)能在 O(n log log n) 时间内找出 [2, n] 内的所有素数。思路朴素而漂亮:

找到一个还没被划掉的数 p,它必然是素数;然后把它的所有倍数(p², p²+p, p²+2p, ...)都划掉。

为什么从 开始?因为 p × kk < p)一定在某个更小的素数那一轮就被划过了。

实现要点

for (int p = 2; p * p <= n; ++p) {
  if (isPrime[p]) {
    for (int i = p * p; i <= n; i += p) isPrime[i] = false;
  }
}

外层循环只到 √n —— 任何合数 c ≤ n 必有一个因子 ≤ √c ≤ √n,所以 √n 之后的数如果还没被划掉就一定是素数。

复杂度

  • 时间:O(n log log n) —— 比朴素的 O(n √n) 快非常多
  • 空间:O(n) 的标记数组

在动画里看什么

  • 深蓝:当前选中的素数 p
  • 暖红:正在被划掉的合数 i = k·p
  • 绿色:已经确认是素数
  • 灰色 + 删除线:已经被划掉的合数
  • 数表分 10 列排列,便于看清楚”每隔 p 个划一个”的节奏