<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=91.108.28.61&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=91.108.28.61&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/91.108.28.61"/>
		<updated>2026-09-01T03:29:37Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B0%D0%B7%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BD%D0%B0_%D0%BC%D0%BD%D0%BE%D0%B6%D0%B8%D1%82%D0%B5%D0%BB%D0%B8_(%D1%84%D0%B0%D0%BA%D1%82%D0%BE%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F)&amp;diff=64481</id>
		<title>Разложение на множители (факторизация)</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A0%D0%B0%D0%B7%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BD%D0%B0_%D0%BC%D0%BD%D0%BE%D0%B6%D0%B8%D1%82%D0%B5%D0%BB%D0%B8_(%D1%84%D0%B0%D0%BA%D1%82%D0%BE%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F)&amp;diff=64481"/>
				<updated>2018-03-18T11:36:08Z</updated>
		
		<summary type="html">&lt;p&gt;91.108.28.61: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение | definition=&lt;br /&gt;
''Факторизация'' - представление объекта в виде произведения других объектов.&lt;br /&gt;
}}&lt;br /&gt;
{{Определение | definition=&lt;br /&gt;
''Разложение на множители'', или ''Факторизация целых чисел'' - представление числа в виде [[Основная теорема арифметики#Основная теорема арифметики#Собственно теорема | произведения его множителей]].&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Определение | definition=&lt;br /&gt;
''Перебор делителей'' — алгоритм факторизации или тестирования простоты числа путем полного перебора всех возможных потенциальных делителей.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Перебор делителей ==&lt;br /&gt;
=== Наивная реализация &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt; ===&lt;br /&gt;
==== Основная идея ====&lt;br /&gt;
[[Основная теорема арифметики#Основная теорема арифметики#Собственно теорема | Основная теорема арифметики]], в купе с утверждением, что &amp;lt;tex&amp;gt;\forall x, y \in \mathbb{N}~~x&amp;lt;y \Longrightarrow&amp;lt;/tex&amp;gt; {{Acronym|&amp;lt;tex&amp;gt;\left( \dfrac{x}{y} &amp;lt; 1 \right)&amp;lt;/tex&amp;gt;|т.е. y не делит x нацело}}, позволяют нам ограничить пространство поиска делителей числа &amp;lt;tex&amp;gt;\mathtt{number}&amp;lt;/tex&amp;gt; интервалом &amp;lt;tex&amp;gt;[2; \mathtt{number}]&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Заметим, что если &amp;lt;tex&amp;gt;\mathtt{number} = \prod p_i = p_1 * p_2 * \dots * p_{j-1} * p_j * p_{j+1} * \dots * p_n&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\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&amp;lt;/tex&amp;gt;. Таким образом, мы можем делить &amp;lt;tex&amp;gt;\mathtt{number}&amp;lt;/tex&amp;gt; на его {{Acronym|делители|множители}}  последовательно и в любом порядке. Тогда будем хранить &amp;lt;tex&amp;gt;\mathtt{curNum} \colon \mathtt{curNum} * \prod \mathtt{result_i} =\mathtt{number}&amp;lt;/tex&amp;gt; - произведение оставшихся множителей.&lt;br /&gt;
==== Псевдокод нахождения простых множителей ====&lt;br /&gt;
Алгоритм работает за &amp;lt;tex&amp;gt;O(k)&amp;lt;/tex&amp;gt;, где k - количество простых множителей.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
   '''function''' &amp;lt;tex&amp;gt;\mathrm{getMultipliers}&amp;lt;/tex&amp;gt;(number: '''int'''): '''vector&amp;lt;int&amp;gt;'''&lt;br /&gt;
       &amp;lt;font color=green&amp;gt;// сюда складываем множители&amp;lt;/font&amp;gt;&lt;br /&gt;
       result = '''vector&amp;lt;int&amp;gt;'''&lt;br /&gt;
       &amp;lt;font color=green&amp;gt;// число, у которого осталось найти множители; &amp;lt;/font&amp;gt;&lt;br /&gt;
       curNum = number&lt;br /&gt;
        &amp;lt;font color=green&amp;gt;// число, на которое пытаемся делить&amp;lt;/font&amp;gt;&lt;br /&gt;
       probe = 2&lt;br /&gt;
       '''while''' curNum &amp;lt;tex&amp;gt;\ne&amp;lt;/tex&amp;gt; 1&lt;br /&gt;
           '''if''' curNum '''mod''' probe &amp;lt;tex&amp;gt;\ne 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
               &amp;lt;font color=green&amp;gt;// проверены все множители из [2; probe]&amp;lt;/font&amp;gt;&lt;br /&gt;
               probe++&lt;br /&gt;
           '''else'''&lt;br /&gt;
               &amp;lt;font color=green&amp;gt;// делим пока делится&amp;lt;/font&amp;gt;&lt;br /&gt;
               curNum /= probe&lt;br /&gt;
               result += [probe]&lt;br /&gt;
        '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
==== Псевдокод нахождения делителей ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    '''function''' &amp;lt;tex&amp;gt;\mathrm{getDividers}&amp;lt;/tex&amp;gt;(number: '''int'''): '''vector&amp;lt;int&amp;gt;'''&lt;br /&gt;
        &amp;lt;font color=green&amp;gt;// массив полученных делителей&amp;lt;/font&amp;gt;&lt;br /&gt;
        result = '''vector&amp;lt;int&amp;gt;''' &lt;br /&gt;
        &amp;lt;font color=green&amp;gt;// перебираем все потенциальные делители&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' probe = 2 '''to''' number&lt;br /&gt;
            '''if''' number '''mod''' probe = 0&lt;br /&gt;
                &amp;lt;font color=green&amp;gt;// probe делит number нацело&amp;lt;/font&amp;gt;&lt;br /&gt;
                result += [probe]&lt;br /&gt;
        '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
=== Улучшенная реализация &amp;lt;tex&amp;gt;O(\sqrt{n})&amp;lt;/tex&amp;gt; ===&lt;br /&gt;
==== Основная идея ====&lt;br /&gt;
Из определения: &amp;lt;tex&amp;gt;\sqrt{n} * \sqrt{n} = n&amp;lt;/tex&amp;gt;. Логично, что:&lt;br /&gt;
{|&lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|rowspan=&amp;quot;2&amp;quot;| &amp;lt;tex&amp;gt;\bigg\{&amp;lt;/tex&amp;gt;&lt;br /&gt;
|&amp;lt;tex&amp;gt;x * y = \mathtt{number}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|rowspan=&amp;quot;2&amp;quot;| &amp;lt;tex&amp;gt;\Longrightarrow x &amp;gt; \sqrt{\mathtt{number}}&amp;lt;/tex&amp;gt; &lt;br /&gt;
|-align=&amp;quot;center&amp;quot;&lt;br /&gt;
|&amp;lt;tex&amp;gt;y &amp;lt; \sqrt{\mathtt{number}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
Таким образом, любой делитель &amp;lt;tex&amp;gt;d_0 &amp;gt; \sqrt{\mathtt{number}}&amp;lt;/tex&amp;gt; однозначно связан с некоторым &amp;lt;tex&amp;gt;d_1 &amp;lt; \sqrt{\mathtt{number}}&amp;lt;/tex&amp;gt;. Если мы найдем все делители до &amp;lt;tex&amp;gt;\sqrt{\mathtt{number}}&amp;lt;/tex&amp;gt;, задача может считаться решенной.&lt;br /&gt;
==== Псевдокод ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    '''function''' &amp;lt;tex&amp;gt;\mathrm{getDividers}&amp;lt;/tex&amp;gt;(&amp;lt;tex&amp;gt;\mathtt{number}&amp;lt;/tex&amp;gt;: '''int'''): '''vector&amp;lt;int&amp;gt;'''&lt;br /&gt;
         result = '''vector&amp;lt;int&amp;gt;'''&lt;br /&gt;
         '''for''' probe = 2 '''to''' &amp;lt;tex&amp;gt;\sqrt{\mathtt{number}}&amp;lt;/tex&amp;gt; &amp;lt;font color=green&amp;gt;// &amp;lt;--- обновляем верхнюю границу перебора&amp;lt;/font&amp;gt;&lt;br /&gt;
            '''if''' number '''mod''' probe = 0&lt;br /&gt;
                result += [probe]&lt;br /&gt;
                result += [&amp;lt;tex&amp;gt;\mathtt{number}&amp;lt;/tex&amp;gt; / probe] &amp;lt;font color=green&amp;gt;// &amp;lt;--- записываем сопряженный делитель&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
=== Проверка числа на простоту. Множители ===&lt;br /&gt;
Алгоритм можно переделать для нахождения простых чисел. Число будет простым, если у него не окажется {{Acronym|множителей|и делителей}} кроме 1 (алгоритмы не проверяют делимость на 1) и самого числа (улучшенная реализация опускает этот делитель). Исключительный случай: &amp;lt;tex&amp;gt;\mathtt{number} = 2&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Вообще говоря, представленный выше алгоритм &amp;lt;tex&amp;gt;\mathrm{getMultipliers}&amp;lt;/tex&amp;gt; ищет простые множители. Чтобы получить разложения на множители необходимо реализовать [[Генерация комбинаторных объектов в лексикографическом порядке|перебор разбиений]] мультимножества простых множителей на подмножества, тогда, перемножив элементы подмножеств, мы получим множители. &lt;br /&gt;
== Предподсчет ==&lt;br /&gt;
{{main|Решето Эратосфена}}&lt;br /&gt;
=== Основная идея ===&lt;br /&gt;
Решето Эратосфена позволяет не только находить простые числа, но и находить простые множители числа. Для этого необходимо хранить (помимо самого &amp;quot;решета&amp;quot;) массив простых чисел, на которое каждое число делится (достаточно одного простого делителя).&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
    &amp;lt;font color=green&amp;gt;// возвращает только дополнительный массив&amp;lt;/font&amp;gt;&lt;br /&gt;
    '''function''' &amp;lt;tex&amp;gt;\mathrm{sieveOfEratosthenes}&amp;lt;/tex&amp;gt;(n: '''int'''): '''int[n]'''&lt;br /&gt;
        result = [n]&lt;br /&gt;
        &amp;lt;font color=green&amp;gt;// выбираем следующий простой делитель&amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' i = 2 '''to''' &amp;lt;tex&amp;gt;\sqrt{\mathtt{n}}&amp;lt;/tex&amp;gt;&lt;br /&gt;
            '''if''' result[i] &amp;lt;tex&amp;gt;\ne&amp;lt;/tex&amp;gt; ''null''&lt;br /&gt;
                &amp;lt;font color=green&amp;gt;// {{Acronym|записываем |в этой реализации и переписываем тоже}}делитель в элементы массива,&lt;br /&gt;
                // соответствующие числа которых делятся нацело&amp;lt;/font&amp;gt;&lt;br /&gt;
                shuttle = &amp;lt;tex&amp;gt;\mathtt{i}^2&amp;lt;/tex&amp;gt;&lt;br /&gt;
                '''while''' shuttle &amp;lt;tex&amp;gt;\leqslant&amp;lt;/tex&amp;gt; n&lt;br /&gt;
                    result[shuttle] = i&lt;br /&gt;
                    shuttle += i&lt;br /&gt;
        '''return''' result&lt;br /&gt;
&lt;br /&gt;
    '''function''' &amp;lt;tex&amp;gt;\mathrm{getMultipliers}&amp;lt;/tex&amp;gt;(number: '''int'''): '''vector&amp;lt;int&amp;gt;'''&lt;br /&gt;
        result = '''vector&amp;lt;int&amp;gt;'''&lt;br /&gt;
        &amp;lt;font color=green&amp;gt;// получаем дополненное решето Эратосфена&amp;lt;/font&amp;gt;&lt;br /&gt;
        sieve = &amp;lt;tex&amp;gt;\mathrm{sieveOfEratosthenes}&amp;lt;/tex&amp;gt;(number)&lt;br /&gt;
        &amp;lt;font color=green&amp;gt;// следующее временное значение получаем&lt;br /&gt;
        // делением предыдущего на простой делитель из решета&amp;lt;/font&amp;gt;&lt;br /&gt;
        curNum = number&lt;br /&gt;
        '''while''' sieve[curNum] &amp;lt;tex&amp;gt;\ne&amp;lt;/tex&amp;gt; ''null''&lt;br /&gt;
            result += [sieveNum]&lt;br /&gt;
            curNum /= sieve[curNum]&lt;br /&gt;
        result += [curNum]&lt;br /&gt;
        '''return''' result&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
== См. также ==&lt;br /&gt;
*[[Решето Эратосфена]]&lt;br /&gt;
*[[Основная теорема арифметики]]&lt;br /&gt;
*[[Дискретная математика, алгоритмы и структуры данных#Комбинаторика | Комбинаторика]]&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
* Маврин П.Ю. - Лекция по алгоритмам над простыми числами (2016)&lt;br /&gt;
* [https://ru.wikipedia.org/wiki/Простое_число https://ru.wikipedia.org/wiki/Простое_число]&lt;br /&gt;
[[Категория: Алгоритмы алгебры и теории чисел]]&lt;/div&gt;</summary>
		<author><name>91.108.28.61</name></author>	</entry>

	</feed>