Решета
Здесь мы будем находить все простые числа от до .
Решето Эратосфена
Решето Эратосфена — алгоритм нахождения списка простых чисел.
Идея простая. Запишем ряд чисел . Вычеркнем из него все числа, делящиеся на , кроме, конечно, . Затем вычеркнем все числа, делящиеся на , кроме . Число уже вычеркнуто, и все числа, кратные , тоже. Поэтому идём дальше. Вычеркиваем все числа, делящиеся на , кроме . Ну и продолжаем так, пока не дойдем до конца.
Итого, мы для каждого простого числа вычёркиваем все дальнейшие числа, кратные ему.
Реализовывать программно это можно по-разному, но самый простой способ —
завести битовый массив is_prime.
Если число вычеркнуто, то .
Вообще можно оставить лишние бита в начале и сделать нормальную индексацию.
input const int n
array[bool] is_prime[n+1] = [true, true, ..., true]
for int i = 2; i <= n; i++:
if is_prime[i]:
for int j = 2 * i; j <= n; j += i:
is_prime[j] = falseЕсть несколько очевидных оптимизаций, которые стоит сразу же применить.
Во-первых, начинать вычёркивать кратные числа можно с , а не с . Ведь все составные числа, кратные и меньшие были вычеркнуты до этого, потому что у них был делитель, меньший .
Во-вторых, внешний цикл можно сделать до . Пусть — простое число, большее . Его наименьшее кратное, которое можно вычеркнуть — . Оно будет находиться за диапазоном поиска простых, ведь .
С учётом всех оптимизаций, получаем код
input const int n
array[bool] is_prime[n+1] = [true, true, ..., true]
for int i = 2; i * i <= n; i++:
if is_prime[i]:
for int j = i * i; j <= n; j += i:
is_prime[j] = falseПроанализируем время работы алгоритма.
Будем измерять число установок в битовом массиве is_prime.
Для каждого простого числа в диапазоне от до мы сделаем установок. Количество чисел в диапазоне от до , которые кратны , равно . Тогда общее количество установок, сделанное алгоритмом, равно
где — константа Мейсселя-Мертенса.
При этом в не оптимизированном алгоритме количество установок равно
Линейное решето Эратосфена
Основная проблема решета Эратосфена в том, что мы неизбежно помечаем некоторые числа как составные несколько раз. Мы помечаем число как составное столько раз, сколько у него различных простых делителей.
Пусть — минимальный простой делитель числа . Любое число тогда представимо в виде , где у нет простых делителей, меньших .
Давайте для каждого числа считать .
Заведем массив d, в котором будем хранить найденные значения.