Разложение на множители (факторизация) — различия между версиями
Senya (обсуждение | вклад) (Метки: правка с мобильного устройства, правка из мобильной версии) |
Tolsi (обсуждение | вклад) м (вот так это работает) |
||
| Строка 80: | Строка 80: | ||
'''function''' sieveOfEratosthenes(n: '''int'''): '''int'''[n] | '''function''' sieveOfEratosthenes(n: '''int'''): '''int'''[n] | ||
result = [n] | result = [n] | ||
| + | result[n] = n | ||
<font color=green>// выбираем следующий простой делитель</font> | <font color=green>// выбираем следующий простой делитель</font> | ||
'''for''' i = 2 '''to''' <tex>\sqrt{n}</tex> | '''for''' i = 2 '''to''' <tex>\sqrt{n}</tex> | ||
| − | '''if''' result[i] = | + | '''if''' result[i] = 0 |
<font color=green>// записываем делитель в элементы массива, | <font color=green>// записываем делитель в элементы массива, | ||
// соответствующие числа которых делятся нацело</font> | // соответствующие числа которых делятся нацело</font> | ||
Версия 22:17, 20 мая 2018
| Определение: |
| Факторизация (англ. factorization) — представление объекта в виде произведения других объектов. |
| Определение: |
| Разложение на множители, или Факторизация целых чисел (англ. integer factorization) — представление числа в виде произведения его множителей. |
Перебор делителей
| Определение: |
| Перебор делителей (англ. Trial division) — алгоритм факторизации или тестирования простоты числа путем полного перебора всех возможных потенциальных делителей. |
Наивная реализация O(n)
Основная теорема арифметики, в купе с утверждением, что не делит нацело: , позволяют нам ограничить пространство поиска делителей числа интервалом .
Основная идея
Заметим, что если = , то . Таким образом, мы можем делить на его делители (множители) последовательно и в любом порядке. Тогда будем хранить — произведение оставшихся множителей.
Псевдокод нахождения простых множителей
Так как простых множителей не может быть больше, чем , а в худшем случае (когда число простое, и на каждое итерации увеличивается на ) он работает за , то, следовательно, алгоритм работает за .
function getMultipliers(number: int): vector<int>
// сюда складываем множители
result = vector<int>
// число, у которого осталось найти множители
curNum = number
// число, на которое пытаемся делить
probe = 2
while curNum 1
if curNum mod probe 0
// проверены все множители из [2; probe]
probe++
else
// делим пока делится
curNum /= probe
result += [probe]
return result
Псевдокод нахождения делителей
function getDividers(number: int): vector<int>
// массив полученных делителей
result = vector<int>
// перебираем все потенциальные делители
for probe = 2 to number
if number mod probe = 0
// probe делит number нацело
result += [probe]
return result
Улучшенная реализация
Основная идея
Из определения: . Логично, что:
Таким образом, любой делитель однозначно связан с некоторым . Если мы найдем все делители до , задача может считаться решенной.
Псевдокод
function getDividers(number: int): vector<int>
result = vector<int>
for probe = 2 to //обновляем верхнюю границу перебора
if number mod probe = 0
result += [probe]
result += [number / probe] // записываем сопряженный делитель
return result
Проверка числа на простоту
Алгоритм можно переделать для нахождения простых чисел. Число будет простым, если у него не окажется множителей (и делителей) кроме (алгоритмы не проверяют делимость на ) и самого числа (улучшенная реализация опускает этот делитель).
Предподсчет
Основная идея
Решето Эратосфена (англ. Sieve of Eratosthenes) позволяет не только находить простые числа, но и находить простые множители числа. Для этого необходимо хранить (помимо самого "решета") массив простых чисел, на которое каждое число делится (достаточно одного простого делителя).
Псевдокод
// возвращает только дополнительный массив
function sieveOfEratosthenes(n: int): int[n]
result = [n]
result[n] = n
// выбираем следующий простой делитель
for i = 2 to
if result[i] = 0
// записываем делитель в элементы массива,
// соответствующие числа которых делятся нацело
shuttle =
while shuttle n
result[shuttle] = i
shuttle += i
return result
function getMultipliers(number: int): vector<int>
result = vector<int>
// получаем дополненное решето Эратосфена
sieve = sieveOfEratosthenes(number)
// следующее временное значение получаем
// делением предыдущего на простой делитель из решета
curNum = number
while curNum 1
result += sieve[curNum]
curNum /= sieve[curNum]
return result
См. также
Источники информации
- Маврин П.Ю. — Лекция по алгоритмам над простыми числами (2016)
- https://ru.wikipedia.org/wiki/Простое_число