И решето Эратосфена, и решето для средневековой головоломки
являются специальными случаями обобщенного
модульного решета. Пусть m1, т2, т3, ..., mt—множество из t целых чисел (называемых
модулями).
Для каждого mi рассмотрим пi
арифметических прогрессий
mik+аij, j=1,2, .... ni.
Задача состоит в отыскании всех целых чисел, заключенных в
пределах между A и B, которые
для каждого mi, одновременно принадлежат одной
из ni прогрессий. В решете Эратосфена мы имеем m1=2, m2=3, m3=5,..., mi=р (наибольшее простое число, меньшее или равное N), ni=mi-1 и аij=j. В задаче о женщине и яйцах mi=i+1, ni=l, 1
Если модули попарно взаимно просты, то мы можем объединить все
прогрессии и получить одно множество
из Пn1; прогрессий с модулем Пmi. Это
осуществляется повторным применением следующей техники объединения прогрессий m1k+a1
и m2k+а2 в одну прогрессию т1m2k+а. Поскольку по предположению наибольший общий делитель т1 и m2
равен единице, алгоритм Евклида гарантирует существование целых чисел и и v, таких, что m1u+m2v=1. Выбирая a=m1ua2-m2va1, мы
находим, что x
Пользу обобщенного модульного решета можно ощутить, рассматривая
задачу проверки первого миллиона чисел Фибоначчи с целью отыскания полных
квадратов. Поскольку
мы получаем, что
F1000000 < 10200000
т. е. F1000000 имеет более
200000 десятичных знаков. Очевидно, «лобовой» метод порождения первого
миллиона чисел Фибоначчи и проверки каждого из них, не является ли оно полным
квадратом, не осуществим, но методом решета вычисление можно легко провести за
несколько минут.
Вычисление начинается с установления в памяти миллиона разрядов
для характеристического вектора, i-й разряд представляет
целое число Fi; если этот разряд равен единице,
то F, может быть квадратом, если он равен нулю, то Fi квадратом быть не может.
Сначала все разряды будут единицами, и в процессе отсеивания на каждом шаге
некоторые из этих разрядов становятся нулями. После окончания просеивания, если
окажется, что какой-либо из разрядов равен единице, то соответствующее число
Фибоначчи нужно исследовать на предмет, не является ли оно полным квадратом.
Миллион разрядов памяти, требующихся для характеристического вектора,— это много,
но не чрезмерно; например, в машине с 32-разрядными словами потребуется только
31250 слов памяти.
Рассмотрим последовательность Фибоначчи по модулю р, где р — простое число. Пусть это будет последовательность P1, P2, P3, …, определяемая следующим образом:
Р1 =Р2 = 1, Pi+1=Pi-1 +Pi(mod p).
Эта последовательность периодическая, причем период начинается
с P1=l.
Для доказательства этого утверждения рассмотрим p2+l упорядоченных пар целых чисел
(Р1, Р2),
(Р2 , Рз), .... (Pp2,
Pp2+1), (Pp2+1, Pp2+2).
Поскольку по модулю р
существует только р2
различных упорядоченных пар целых чисел, две из этих пар должны совпадать.
Пусть (Рr,
Pr+1) и (Ps,
Ps+1) будут самыми левыми совпадающими
парами
(Рr, Рr+1) = (Рs, Рs+1), r<s.
Если r>1, то мы имеем
(Рr-1, Pr) = (Ps-1,
Ps),
что противоречит предположению о том, что (Pr,
Рr+1) и (Ps, Ps+1)
— самые левые совпадающие пары. Таким образом, числа Фибоначчи образуют по
модулю р периодическую последовательность,
начинающуюся с P1 и такую, что Рi=Рi+nTp для некоторого Tp и всех n
По модулю любого числа п
существует несколько квадратов (обычно называемых квадратичными вычетами по модулю п1) и несколько неквадратов. Например, 0, 1, 2 и 4 являются квадратичными
вычетами по модулю 7, в то время как 3, 5 и 6 являютса квадратичными невычетами. Таким образом, любое из чисел m=3, 5-или 6 (mod 7) не может быть
квадратом, потому что оно является квадратичным невычетом по модулю 7.
Поскольку для каждого простого р
числа Фибоначчи по модулю р образуют
периодическую последовательность с периодом Тp, мы производим отсеивание, используя арифметические
прогрессии Tpk+i для
каждого i, такого, что Рi является квадратичным
невычетом по модулю р. Для
иллюстрации процесса отсеивания рассмотрим случай р=7. Ряд Фибоначчи по модулю 7 представляет собой
последовательность из 16 элементов
1, 1,
2, 3, 5, 1, 6, 0, 6, 6, 5, 4, 2, 6, 1, 0,
повторяющихся периодически с периодом Т7==16.
Поскольку 3, 5 и 6 — квадратичные невычеты, мы знаем теперь, что F4+16n, F5+16n, F7+16n , F9+16n , F10+16n, F11+16n и F14+16n не являются квадратами для. n
После отсеивания квадратичных невычетов первых 32 простых чисел
мы обнаруживаем, что все значения разрядов, кроме первого, второго и
двенадцатого, изменены на нули. Не изменившие значений разряды соответствуют
трем числам F1=F2=
1 и F12=144; поэтому можно заключить, что среди
первого миллиона чисел Фибоначчи только они являются квадратами. На самом деле
доказано, что только они являются квадратами среди чисел Фибоначчи.
Рекурсивное решето
Существует много решет, в которых модули m1,
т2, ... заранее не заданы; значение тi будет зависеть от чисел, не удаленных после просеивания по модулю
mi-1.
Многие решета строятся рекурсивным образом. Фактически, решето Эратосфена
обычно так и строится: после выписывания чисел 2, 3, ..., N мы вычеркиваем все числа, кратные 2, кроме самой двойки. Затем,
поскольку наименьшее оставшееся число, чьи кратные остались неудаленными, равно
трем, удаляются все числа, кратные трем, кроме самой тройки, и т. д.
Заметим, что на каждом шаге первое удаленное число является квадратом
числа, с которого начинается просеивание; например, первым числом, исключаемым
двойкой, будет 4, тройкой — 9 и т. д. Когда число, относительно которого
производится просеивание, становится больше
Обычно мы удваиваем размер ячеек решета Эратосфена, осуществляя
предпросеивание для двойки; другими
словами, мы начинаем только с нечетных чисел, отсеивая кратные 3, 5, 7, 11 и т.
д. Пусть Х — двоичный набор; тогда рекурсивный
вариант решета Эратосфена (с предпросеиванием для двойки) для нечетных простых
чисел до 2N+1 показан в алгоритме 4.5.
Х ¬
(1, 1, .... 1)
for k=3 to
[X(k-1)/2 представляет нечетное число k]
if X(k-1)/2 =1 then for i =k2 to 2N+1 by 2k do X(i-1)/2¬0
for k=1 to N do if Xk=1 then вывести 2k+1
Алгоритм 4.5. Решето Эратосфена
для нечетных простых чисел.
Другое хорошо известное рекурсивное решето порождает счастливые числа. Из списка чисел 1, 2, 3, 4, 5, ... удаляется
каждое второе число, в результате чего получается список 1, 3, 5, 7, 9.
Поскольку тройка является первым числом (исключая единицу), которое не
использовано в качестве просеивающего, из оставшихся чисел мы удаляем каждое
третье число, получая в результате список 1, 3, 7, 9, 13, 15, 19, 21,...
.Теперь удаляется каждое седьмое число, в результате чего получается список 1,
3, 7, 9,13, 15, 21, ... . Числа, которые никогда не удаляются из списка,
называются «счастливыми».
Несмотря на большую схожесть решета Эратосфена и решета для получения
счастливых чисел, последнее реализуется труднее. Трудность возникает потому,
что числа, отсеиваемые на k-м шаге, позиционно зависят от еще неисключенных
элементов, а не от элементов первоначального множества. В предположении, что
для представления чисел используется двоичная последовательность в решете для
счастливых чисел нужно будет считать, скажем, каждый седьмой единичный разряд
вместо вообще седьмого разряда. Эта задача существенно облегчается, если
использовать бирки. Вместо использования
полного машинного слова для представления возможных решений, которые мы должны
просеять, мы используем часть этого слова для хранения счетчика числа единиц в
остальной части слова. Например, в ЭВМ со словом, состоящим из четырех байтов,
каждый из которых состоит из восьми разрядов, мы можем использовать слово так,
как это показано на рис. 4.13. Правый байт содержит счетчик числа единичных
разрядов в трех левых байтах. С использованием бирок отыскание t-го невычеркнутого элемента (t-гo единичного
разряда) легко осуществляется путем суммирования бирок до тех пор, пока сумма S не станет
большей или равной t; соответствующий элемент будет (S—t+1)-м единичным разрядом справа в
левых байтах последнего слова, чья бирка суммировалась.
Очевидно, навешивание бирок не приводит к экономии времени,
если из каждого слова исключается один или более разрядов. По этой причине
имеет смысл осуществить просеивание для нескольких шагов без бирок и начинать
их использовать, когда подлежащие отсеиванию элементы становятся достаточно
редкими. Точное число шагов, прогоняемых без бирок, зависит от типа решета и
размера слова. Например, для решета счастливых чисел с 32-разрядными словами и
8-разрядной биркой лучше сделать первые три-четыре шага без бирки.
Навешивание бирок можно расширить до бирок более высокого
порядка, выбирая целое т
Рекурсивное решето несколько другого характера можно использовать
для вычисления следующей последовательности U. Вначале U=(1, 2). Если
вопрос о вхождении в U решен для всех
целых чисел, меньших п, то пÎU тогда и только тогда, когда п
является суммой единственной пары различных элементов из U. Таким образом U=(1, 2, 3, 4, 6, 8, 11,
13, 16, 18, 26,...). Эту последовательность можно вычислить с помощью двух параллельных
просеиваний; целое должно быть просеяно (должно быть суммой, получаемой не
менее чем одним способом) и не должно быть отсеяно (должно быть суммой,
получаемой не более, чем одним способом). Используем два двоичных вектора. Для i>2
Хi=1,
если и только если i представимо в виде суммы не менее чем
одним способом.
Уi=1,
если и только если i представимо в виде суммы не более чем
одним способом.
«Двойное решето» для вычисления элементов U до некоторого числа N
приводится в алгоритме 4.6. Значение счетчика k увеличивается
до тех пор, пока оно не достигнет первого целого числа, большего предыдущего
элемента из U, представимого точно
одним способом. Это целое принадлежит U,
и поэтому разряды, соответствующие всем целым k+i для i<.k, должны
быть обновлены.
X ¬ (1, 1, 0,
0, ....,0)
У ¬ (1, 1, 1,
1, ..., 1)
k ¬ 1
for i=1 to N do if Xi
Алгоритм
4.6. Двойное
решето для последовательности U.
Литература
Рейнгольд Э. и др.
Комбинаторные алгоритмы: теория и практика.
Ахо А., Хопкрофт Дж.,
Ульман Дж. Построение и анализ вычислительных алгоритмов.
Гудман С., Хидетниеми С. Введение в разработку и анализ
алгоритмов.
Вирт Н. Алгоритмы +
структуры данных = программы.
Гэри М., Джонсон Д.
Вычислительные машины и труднорешаемые задачи.
Niemann, Tomas. Сортировка и поиск:
Рецептурный справочник Перевод с английского П.Н.Дубнер (infoscope@glasnet.ru).
Сибуя М., Ямамото Е. Алгоритмы обработки данных.
Aho, Alfred V. and Jeffrey D. Ullman [1983]. Data Structures and Algorithms
Cormen, Thomas H., Charles E. Leiserson and Ronald L.
Rivest [1990]. Introduction to
Algorithms
Knuth, Donald E. [1998]. The Art of Computer Programming, Volume 3, Sorting and
Searching. Addison-Wesley, Reading, Massachusetts.
Pearson, Peter K. [1990]. Fast Hashing of Variable-Length
Text Strings
Pugh, William [1990]. Skip Lists: A Probabilistic Alternative to Balanced Trees.
Communications of the ACM, 33(6):668-676, June
1990.
Глоссарий
Term
|
Термин
|
sort by
insertion
|
сортировка вставками
|
replacement
selection
|
выбор с замещением
|
polyphase
merge sort
|
многофазное слияние
|
array
|
массив
|
linked list
|
линейный список
|
comparison
|
сравнение
|
in-place
|
на месте (без дополнительных массивов)
|
stable sort
|
устойчивая сортировка
|
external
sort
|
внешняя сортировка
|
underflow
|
вырождение
|
overflow
|
переполнение
|
red-black
tree
|
красно-черное дерево
|
B-tree
|
Б-дерево
|
skip list
|
слоёный список
|
rotation
|
|