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