Основная идея сегментированного сита состоит в том, чтобы выбрать простые числа рассева, меньшие квадратного корня из n, выбрать достаточно большой размер сегмента, который, тем не менее, уместиться в памяти, а затем просеивать каждый из сегментов по очереди, начиная с самых маленьких. В первом сегменте вычисляется наименьшее кратное каждому простому рассеву, находящемуся внутри сегмента, затем кратные количеству просеивающего стержня обычным образом отмечаются как составные; когда все простые числа просеивания были использованы, оставшиеся немаркированные числа в сегменте являются простыми. Затем, для следующего сегмента, для каждого начального числа рассева вам уже известно первое кратное в текущем сегменте (именно кратное число завершило рассев для этого начального числа в предыдущем сегменте), поэтому вы просеиваете каждое начальное число просеивания и т. Д. пока вы не закончите.
Размер n не имеет значения, за исключением того, что для большего n потребуется больше времени для просеивания, чем для меньшего n; размер имеет значение, это размер сегмента, который должен быть настолько большим, насколько это удобно (скажем, размер кэша первичной памяти на машине).
Вы можете увидеть простую реализацию сегментированного сита здесь. Обратите внимание, что сегментированное решето будет намного быстрее, чем решето очереди приоритетов О'Нила, упомянутое в другом ответе; Если вам интересно, здесь есть реализация.
РЕДАКТИРОВАТЬ: Я написал это для другой цели, но я покажу это здесь, потому что это может быть полезно:
Хотя Сито Эратосфена очень быстрое, для него требуется O (n) места. Это можно уменьшить до O (sqrt (n)) для простых чисел просеивания плюс O (1) для битового массива, выполняя просеивание в последовательных сегментах. В первом сегменте вычисляется наименьшее кратное каждому простому просеиванию, которое находится в сегменте, затем кратные количеству просеивающего стержня отмечаются как составные обычным способом; когда все простые числа просеивания были использованы, оставшиеся немаркированные числа в сегменте являются простыми. Затем для следующего сегмента наименьшее значение, кратное каждой заправке просеивания, является кратным, которое завершило рассев в предыдущем сегменте, и поэтому рассев продолжается до завершения.
Рассмотрим пример сита от 100 до 200 в сегментах по 20. Пять простых чисел рассева - 3, 5, 7, 11 и 13. В первом сегменте от 100 до 120 битовый массив имеет десять слотов, причем слот 0 соответствует 101. , слот k, соответствующий 100 + 2k + 1, и слот 9, соответствующий 119. Наименьшее кратное 3 в сегменте равно 105, что соответствует слоту 2; слоты 2 + 3 = 5 и 5 + 3 = 8 также кратны 3. Наименьшее кратное 5 равно 105 в слоте 2, а слот 2 + 5 = 7 также кратно 5. Наименьшее кратное 7 равно 105 в слоте 2, и слот 2 + 7 = 9 также кратно 7. И так далее.
Функция primesRange принимает аргументы lo, hi и delta; lo и hi должны быть четными, причем lo ‹hi, а lo должно быть больше sqrt (hi). Размер сегмента в два раза больше дельты. Ps - это связанный список, содержащий простые числа, меньшие, чем sqrt (hi), с удалением 2, поскольку четные числа игнорируются. Qs - это связанный список, содержащий переход в битовый массив сита наименьшего кратного в текущем сегменте соответствующего простого числа рассева. После каждого сегмента lo увеличивается на удвоенную дельту, поэтому число, соответствующее индексу i ситового битового массива, равно lo + 2i + 1.
function primesRange(lo, hi, delta)
function qInit(p)
return (-1/2 * (lo + p + 1)) % p
function qReset(p, q)
return (q - delta) % p
sieve := makeArray(0..delta-1)
ps := tail(primes(sqrt(hi)))
qs := map(qInit, ps)
while lo < hi
for i from 0 to delta-1
sieve[i] := True
for p,q in ps,qs
for i from q to delta step p
sieve[i] := False
qs := map(qReset, ps, qs)
for i,t from 0,lo+1 to delta-1,hi step 1,2
if sieve[i]
output t
lo := lo + 2 * delta
При вызове primesRange (100, 200, 10) простые числа рассева ps равны [3, 5, 7, 11, 13]; qs изначально имеет значение [2, 2, 2, 10, 8], соответствующее наименьшим кратным 105, 105, 105, 121 и 117, и сбрасывается для второго сегмента на [1, 2, 6, 0, 11], соответствующее наименьшему кратные 123, 125, 133, 121 и 143.
Вы можете увидеть эту программу в действии на странице http://ideone.com/iHYr1f. И в дополнение к приведенным выше ссылкам, если вы интересуетесь программированием с простыми числами, я скромно рекомендую это эссе в моем блоге.
person
user448810
schedule
20.04.2012