Линейное решето Эратосфена

       Основная проблема решета Эратосфена состоит в том, что некоторые числа мы будем помечать как составные несколько раз — а именно столько раз, сколько у них различных простых делителей. Чтобы достичь линейного времени работы, нам нужно придумать способ, как рассматривать все составные числа ровно один раз.

 

Наша цель — посчитать для каждого числа i от в отрезке [2; n] его минимальный простой делитель lp[i]. Кроме того, нам потребуется хранить список всех найденных простых чисел — назовём его вектором pr[].

 

Изначально все величины lp[i] заполним нулями, что означает, что мы пока предполагаем все числа простыми. В ходе работы алгоритма этот массив будет постепенно заполняться.

 

Будем теперь перебирать текущее число i от 2 до n. У нас может быть два случая:

● lp[i] = 0 — это означает, что число i — простое, т. к. для него так и не обнаружилось других делителей, следовательно, надо присвоить lp[i] = i и добавить i в конец списка pr[].

● lp[i]!= 0 — это означает, что текущее число i — составное, и его минимальным простым делителем является lp[i].

 

В обоих случаях дальше начинается процесс расстановки значений в массиве lp[]: мы будем брать числа, кратные i, и обновлять у них значение lp[]. Однако наша цель — научиться делать это таким образом, чтобы в итоге у каждого числа значение lp[] было бы установлено не более одного раза.

 

Утверждается, что для этого можно поступить таким образом. Рассмотрим числа вида:

x_j = i * p_j, где последовательность p_j — это все простые, не превосходящие lp[i] (как раз для этого нам понадобилось хранить список всех простых чисел). У всех чисел такого вида проставим новое значение lp[x_j] — очевидно, оно будет равно p_j.

 




double arrow
Сейчас читают про: