47
правок
Изменения
Нет описания правки
{{Определение | definition=''Факторизация'Перебор делителей'- представление объекта в виде произведения других объектов.}}{{Определение | definition=''Разложение на множители'' — алгоритм факторизации , или тестирования простоты ''Факторизация целых чисел'' - представление числа путем полного перебора всех возможных потенциальных делителейв виде [[Основная теорема арифметики#Основная теорема арифметики#Собственно теорема | произведения его множителей]].}}
{{Определение | definition==Проверка ''Перебор делителей'' — алгоритм факторизации или тестирования простоты числа на простоту за <tex>O(\sqrt{nпутем полного перебора всех возможных потенциальных делителей.}})</tex>==
Заметим, что если <tex>\mathtt{number} = \prod p_i = p_1 * p_2 * \dots * p_{j-1} * p_j * p_{j+1} * \dots * p_n</tex>, то <tex>\left(\dfrac{\mathtt{number}}{p_i}\right) = \prod\limits_{i \ne j} p_i = p_1 * p_2 * \dots * p_{j-1} * p_{j+1} * \dots * p_n</tex>. Таким образом, осуществляя проверку мы можем делить <tex>\mathtt{number}</tex> на делимость его {{Acronym|делители|множители}} последовательно и в любом порядке. Тогда будем хранить <tex>\mathtt{curNum} \colon \mathtt{curNum} * \prod \mathtt{result_i} =\mathtt{number}</tex> - произведение оставшихся множителей.==== Псевдокод нахождения простых множителей ====Алгоритм работает за <tex>O(k)</tex>, где k - количество простых множителей.<code> '''function''' <tex>\mathrm{getMultipliers}</tex>(number: '''int'''): '''vector<int>''' <font color=green>// сюда складываем множители</font> result = '''vector<int>''' <font color=green>// число, у которого осталось найти множители; </font> curNum = number <font color=green>// число, на которое пытаемся делить</font> probe = 2 '''while''' curNum <tex>\ne</tex> 1 '''if''' curNum '''mod''' probe <tex>\ne 0</tex> <font color=green>// проверены все множители из [2; probe]</font> probe++ '''else''' <font color=green>// делим пока делится</font> curNum /= probe result += [probe] '''return''' result</code>==== Псевдокод нахождения делителей ====<code> '''function''' <tex>\mathrm{getDividers}</tex>(number: '''int'''): '''vector<int>''' <font color=green>// массив полученных делителей</font> result = '''vector<int>''' <font color=green>// перебираем все потенциальные делители</font> '''for''' probe = 2 '''to''' number '''if''' number '''mod''' probe = 0 <font color=green>// probe делит number нацело</font> result += [probe] '''return''' result</code>=== Улучшенная реализация <tex>O(\sqrt{n})</tex> и перебирая не более <font color=white>O(√n)</font> ======= Основная идея ====Из определения: <tex>\sqrt{n}* \sqrt{n} = n</tex> чисел. Логично, получаем максимальную оценку времени работы алгоритмачто: {||-align="center"|rowspan="2"| <tex>\bigg\{</tex>|<tex>x * y = \mathtt{number}</tex>|rowspan="2"| <tex>\Longrightarrow x > \sqrt{\mathtt{number}}</tex> |-align="center"|<tex>y < \sqrt{\mathtt{number}}</tex>|}Таким образом, любой делитель <tex>d_0 > \sqrt{\mathtt{number}}</tex> однозначно связан с некоторым <tex>d_1 < \sqrt{\mathtt{number}}</tex>. Если мы найдем все делители до <tex>\sqrt{\mathtt{number}}</tex>, задача может считаться решенной.==== Псевдокод ====<code> '''function''' <tex>\mathrm{getDividers}</tex>O(<tex>\mathtt{number}</tex>: '''int'''): '''vector<int>''' result = '''vector<int>''' '''for''' probe = 2 '''to''' <tex>\sqrt{n\mathtt{number}}</tex> <font color=green>// <--- обновляем верхнюю границу перебора</font> '''if''' number '''mod''' probe = 0 result += [probe] result += [<tex>\mathtt{number}</tex> / probe] <font color=green>// <--- записываем сопряженный делитель</font> '''return''' result</code>=== Проверка числа на простоту. Множители ===Алгоритм можно переделать для нахождения простых чисел. Число будет простым, если у него не окажется {{Acronym|множителей|и делителей}}кроме 1 (алгоритмы не проверяют делимость на 1)и самого числа (улучшенная реализация опускает этот делитель). Исключительный случай: <tex>\mathtt{number} = 2</tex>.
Вообще говоря, представленный выше алгоритм <tex>\mathrm{getMultipliers}</tex> ищет простые множители. Чтобы получить разложения на множители необходимо реализовать [[Генерация комбинаторных объектов в лексикографическом порядке|перебор разбиений]] мультимножества простых множителей на подмножества, тогда, перемножив элементы подмножеств, мы получим множители. == Предподсчет =={{main|Решето Эратосфена}}==Разложение = Основная идея ===Решето Эратосфена позволяет не только находить простые числа, но и находить простые множители числа. Для этого необходимо хранить (помимо самого "решета") массив простых чисел, на множители за которое каждое число делится (достаточно одного простого делителя).=== Псевдокод ===<code> <font color=green>// возвращает только дополнительный массив</font> '''function''' <tex>\mathrm{sieveOfEratosthenes}</tex>O(n: '''int'''): '''int[n]''' result = [n] <font color=green>// выбираем следующий простой делитель</font> '''for''' i = 2 '''to''' <tex>\sqrt{\mathtt{n})}</tex> '''if''' result[i] <tex>\ne</tex> ''null'' <font color=green>// {{Acronym|записываем |в этой реализации и переписываем тоже}}делитель в элементы массива, // соответствующие числа которых делятся нацело</font> shuttle = <tex>\mathtt{i}^2</tex> '''while''' shuttle <tex>\leqslant</tex>n result[shuttle] =i shuttle +=i '''return''' result