Решето Эратосфена (sieve of Eratosthenes) находит все простые числа от 2 до N за : каждое найденное простое вычёркивает свои кратные.
Зачем нужно
Задача: N — натуральное число, найти все простые .
Не из лекции: сравнение с проверкой по одному
Проверить одно число на простоту можно за — см. L01. Если проверять так каждое число до N, выйдет . Решето не проверяет числа по одному, а сразу вычёркивает все составные — почти линейно.
Как работает
Таблица is_prime на элемент, сначала всё ✓, 0 и 1 — ✗. Идём по
:
is_prime[d]= ✗ — составное, пропускаем;is_prime[d]= ✓ — простое, вычёркиваем .
is_prime = [T, T, ..., T] // N + 1 элемент
is_prime[0] = is_prime[1] = F
for d = 2 ... N
если is_prime[d] = T // d — простое
m = 2
while (m * d ≤ N)
is_prime[m * d] = F
m++
for d = 2 ... N
если is_prime[d] = T
print(d)Здесь 2 ... N включает N.
Почему верно
Не из лекции: корректность
Вычёркиваются только числа с — составные. Любое составное вычеркнет его наименьший делитель : этот делитель простой, и при нём дойдёт до .
Когда цикл доходит до ,
is_prime[d]уже окончательный: если составное, его наименьший простой делитель меньше и уже успел его вычеркнуть. Алгоритм опирается на таблицу, которую сам же строит.
Оценки
На лекции: , без доказательства.
Не из лекции: откуда и память
Для простого внутренний цикл делает меньше шагов, поэтому . Сумма обратных простых растёт как . Доказательство — в конспекте L03.
Если бы вычёркивали кратные каждого , а не только простого, получилось бы .
Память — таблица на элемент: .
Тонкости
- растёт очень медленно: при это около 2,9. На практике решето работает почти как линейный проход.
- Память — ограничение: решето до требует гигабайт таблицы (по байту на число).
- Проверку
is_prime[d]нельзя убирать: без неё составные тоже вычёркивали бы кратные, и время выросло бы до . Ответ при этом остался бы верным.
Частые ошибки
- Таблица на N элементов вместо : само N не помещается.
- Забыть
is_prime[0] = is_prime[1] = F— 0 и 1 окажутся «простыми». - Цикл вывода
for d = 2 ... Nбез самого N — простое N потеряется.