<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>RSA on kenji.blog</title><link>http://kenji.blog/ru/tags/rsa/</link><description>Recent content in RSA on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ru</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 05 Sep 2026 22:09:21 +0900</lastBuildDate><atom:link href="http://kenji.blog/ru/tags/rsa/index.xml" rel="self" type="application/rss+xml"/><item><title>Действительно ли квантовые компьютеры уничтожат шифрование RSA? ~ Алгоритм Шора и текущий этап ~</title><link>http://kenji.blog/ru/p/shors-algorithm-and-rsa-breaking/</link><pubDate>Sat, 05 Sep 2026 22:09:21 +0900</pubDate><guid>http://kenji.blog/ru/p/shors-algorithm-and-rsa-breaking/</guid><description>&lt;img src="http://kenji.blog/p/shors-algorithm-and-rsa-breaking/quantum_breaking_rsa_1788613722990.jpg" alt="Featured image of post Действительно ли квантовые компьютеры уничтожат шифрование RSA? ~ Алгоритм Шора и текущий этап ~" />&lt;h2 id="введение-пересечение-криптографии-и-квантовых-компьютеров">Введение: Пересечение криптографии и квантовых компьютеров
&lt;/h2>&lt;p>В современном интернет-обществе основой защиты секретности связи является «криптография с открытым ключом». Наиболее представительным является шифрование RSA, разработанное в 1977 году Роном Ривестом, Ади Шамиром и Леонардом Адлеманом. От покупок в Интернете и просмотра веб-сайтов (HTTPS) до отправки и получения электронной почты, шифрование RSA служит сердцем интернет-инфраструктуры.&lt;/p>
&lt;p>Однако появление «квантовых компьютеров» указывает на возможность того, что эта безопасность может быть разрушена на корню. В СМИ иногда появляются сенсационные заголовки, такие как «Как только квантовый компьютер будет готов, все пароли в мире будут расшифрованы за секунды». Так ли это на самом деле?&lt;/p>
&lt;p>В этой статье подробно рассматривается механизм GNFS (Общий метод решета числового поля) как классический метод дешифрования, а также окончательный алгоритм дешифрования с использованием квантовых компьютеров — «Алгоритм Шора» (Shor&amp;rsquo;s Algorithm). Мы доступно объясним такие концепции, как квантовое преобразование Фурье и поиск периода, и подробно рассмотрим текущее состояние аппаратного обеспечения в эпоху NISQ (Noisy Intermediate-Scale Quantum) и реальные препятствия для взлома RSA-2048.&lt;/p>
&lt;hr>
&lt;h2 id="основа-rsa-сложность-факторизации">Основа RSA: Сложность факторизации
&lt;/h2>&lt;p>Безопасность RSA зависит от математической асимметрии: «Легко перемножить два гигантских простых числа, но крайне сложно найти (факторизовать) исходные простые числа из результата (составного числа)».&lt;/p>
&lt;p>Например, пусть есть $ p = 61 $ и $ q = 53 $. Вычисление $ N = p \times q = 3233 $ мгновенно. Однако, если дано только «3233» и нужно найти исходные простые числа, факторизация требует экспоненциально больше вычислений с ростом числа.&lt;/p>
&lt;p>В текущем стандарте RSA-2048 используется составное число $ N $ длиной 2048 бит (около 617 десятичных цифр). Если мы сможем факторизовать $ N $, шифр будет взломан.&lt;/p>
&lt;h3 id="классический-подход-gnfs-общий-метод-решета-числового-поля">Классический подход: GNFS (Общий метод решета числового поля)
&lt;/h3>&lt;p>Для факторизации математики разрабатывали различные алгоритмы. Самым быстрым для классических компьютеров в настоящее время является ** GNFS (General Number Field Sieve) **.&lt;/p>
&lt;p>GNFS расширяет вычисления в кольце целых чисел до более абстрактного алгебраического числового поля. Основные этапы:&lt;/p>
&lt;ol>
&lt;li>** Выбор полинома **: Найти полином $ f(x) $, корнем которого является $ N $.&lt;/li>
&lt;li>** Сбор данных (просеивание) **: Найти много пар чисел, разложимых на малые простые (гладкие числа). Это самый долгий этап.&lt;/li>
&lt;li>** Генерация и редукция матрицы **: Создать гигантскую разреженную матрицу и решить её методами линейной алгебры.&lt;/li>
&lt;li>** Вычисление квадратного корня **: Найти факторы (простые множители) $ N $.&lt;/li>
&lt;/ol>
&lt;p>Сложность вычисляется как $ O(\exp((\sqrt[3]{\frac{64}{9}} + o(1)) (\log N)^{\frac{1}{3}} (\log \log N)^{\frac{2}{3}})) $ — это «субэкспоненциальное» время.&lt;/p>
&lt;p>В 2020 году исследователи успешно факторизовали RSA-250 (829 бит) с помощью GNFS, потратив около 2700 процессоро-лет. Но для 2048 бит требуемые вычисления превышают возраст Вселенной в триллионы раз, что делает классические методы непрактичными.&lt;/p>
&lt;hr>
&lt;h2 id="козырь-квантовых-компьютеров-алгоритм-шора">Козырь квантовых компьютеров: Алгоритм Шора
&lt;/h2>&lt;p>В 1994 году Питер Шор представил «алгоритм Шора», который решает проблему факторизации на квантовом компьютере за ** полиномиальное время ** ($ O((\log N)^3) $). Это теоретически означает полный взлом RSA.&lt;/p>
&lt;h3 id="общая-схема-алгоритма-шора">Общая схема алгоритма Шора
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">graph TD
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> A[Ввод числа N] --&amp;gt; B[Выбор случайного целого a]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> B --&amp;gt; C{НОД&amp;lt;br&amp;gt;a и N}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> C --&amp;gt;|Больше 1| D[Удача! Найден множитель!]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> C --&amp;gt;|1 Взаимно просты| E[Квантовый компьютер]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> E --&amp;gt; F[Поиск периода r для f_x = a^x mod N&amp;lt;br&amp;gt;через QFT]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> F --&amp;gt; G{Период r четный и&amp;lt;br&amp;gt;a^r/2 ≢ -1 mod N}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> G --&amp;gt;|Да| H[Вычисление НОД gcd_a^r/2 ± 1, N]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> H --&amp;gt; I((Успешная факторизация!))
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> G --&amp;gt;|Нет| B
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="шаг-1-сведение-к-поиску-периода-классическая-часть">Шаг 1: Сведение к поиску периода (Классическая часть)
&lt;/h3>&lt;p>Выбираем $ a $, взаимно простое с $ N $. Рассмотрим последовательность:
$ f(x) = a^x \pmod N $
Эта функция периодична, и задача — найти её период $ r $. Если период $ r $ найден и он четный, то с помощью:
$ (a^{r/2} - 1)(a^{r/2} + 1) \equiv 0 \pmod N $
и алгоритма Евклида мы можем легко найти факторы $ N $.&lt;/p>
&lt;h3 id="шаг-2-суперпозиция">Шаг 2: Суперпозиция
&lt;/h3>&lt;p>Квантовый компьютер готовит два регистра. С помощью вентилей Адамара первый регистр переводится в ** состояние равномерной суперпозиции ** всех возможных значений $ x $.&lt;/p>
&lt;h3 id="шаг-3-квантовое-модульное-возведение-в-степень">Шаг 3: Квантовое модульное возведение в степень
&lt;/h3>&lt;p>Параллельно для всех состояний суперпозиции вычисляется $ a^x \pmod N $.&lt;/p>
&lt;h3 id="шаг-4-квантовое-преобразование-фурье-qft">Шаг 4: Квантовое преобразование Фурье (QFT)
&lt;/h3>&lt;p>Чтобы извлечь информацию о периоде, применяется ** QFT ** к первому регистру. Благодаря конструктивной и деструктивной интерференции, вероятности неправильных периодов гасятся, а вероятность правильного периода $ r $ усиливается.&lt;/p>
&lt;h3 id="шаг-5-измерение-и-непрерывные-дроби">Шаг 5: Измерение и непрерывные дроби
&lt;/h3>&lt;p>После применения QFT измерение первого регистра дает значение, из которого классическим методом непрерывных дробей находится точный период $ r $. Имея $ r $, мы получаем множители $ N $.&lt;/p>
&lt;hr>
&lt;h2 id="возможности-и-проблемы-эпохи-nisq">Возможности и проблемы эпохи NISQ
&lt;/h2>&lt;p>Будет ли RSA взломан завтра? Ответ — однозначное «Нет», из-за аппаратных ограничений.&lt;/p>
&lt;h3 id="эпоха-nisq">Эпоха NISQ
&lt;/h3>&lt;p>Мы находимся в эре устройств NISQ с десятками/сотнями физических кубитов, подверженных сильному шуму. Декогеренция и ошибки вентилей разрушают результаты сложных алгоритмов вроде алгоритма Шора.&lt;/p>
&lt;h3 id="физические-и-логические-кубиты">Физические и логические кубиты
&lt;/h3>&lt;p>Для исправления ошибок требуется &amp;ldquo;квантовая коррекция ошибок&amp;rdquo; (например, Surface Code). Для создания одного идеального логического кубита требуется от 1000 до 10000 физических кубитов (оверхед).&lt;/p>
&lt;h3 id="ресурсы-для-взлома-rsa-2048">Ресурсы для взлома RSA-2048
&lt;/h3>&lt;p>По оценкам 2021 года от Craig Gidney и Martin Ekerå, для взлома RSA-2048 потребуется:&lt;/p>
&lt;ul>
&lt;li>** Логические кубиты **: ~ 4,096&lt;/li>
&lt;li>** Физические кубиты **: ** ~ 20 миллионов ** (при уровне ошибок $10^{-3}$)&lt;/li>
&lt;li>** Время вычислений **: ~ 8 часов&lt;/li>
&lt;/ul>
&lt;p>В конце 2023 года IBM представила процессор &amp;ldquo;Condor&amp;rdquo; с 1,121 кубитом. Масштабирование до ** 20 миллионов ** практических кубитов связано с колоссальными инженерными барьерами. Большинство экспертов считают, что для создания отказоустойчивого квантового компьютера (FTQC) потребуется от 10 до 30 лет или больше.&lt;/p>
&lt;hr>
&lt;h2 id="угроза-store-now-decrypt-later-и-эра-pqc">Угроза &amp;ldquo;Store Now, Decrypt Later&amp;rdquo; и эра PQC
&lt;/h2>&lt;p>Считать, что можно расслабиться на 10 лет, преждевременно. Существует угроза ** &amp;ldquo;Store Now, Decrypt Later&amp;rdquo; (Сохрани сейчас, расшифруй позже) **. Злоумышленники собирают и хранят зашифрованные данные, чтобы расшифровать их, как только квантовые компьютеры станут доступны.&lt;/p>
&lt;p>В ответ на эту угрозу NIST ускоряет стандартизацию ** Постквантовой криптографии (PQC: Post-Quantum Cryptography) **.
Основные направления PQC:&lt;/p>
&lt;ul>
&lt;li>** Криптография на решетках (Lattice-based cryptography) **: На основе задачи LWE (Kyber, Dilithium).&lt;/li>
&lt;li>** Криптография на кодах (Code-based cryptography) **: Сложность декодирования кодов.&lt;/li>
&lt;li>** Многомерная криптография (Multivariate cryptography) **: Системы квадратных уравнений.&lt;/li>
&lt;li>** Хэш-сигнатуры (Hash-based signatures) **: Только на основе хэш-функций.&lt;/li>
&lt;/ul>
&lt;p>Основные платформы, такие как Google Chrome и Apple iMessage, уже начали тестировать и внедрять гибридные PQC решения.&lt;/p>
&lt;h2 id="заключение">Заключение
&lt;/h2>&lt;p>Квантовые компьютеры переходят из области фантастики в реальную инженерную задачу. Алгоритм Шора — это великое интеллектуальное достижение, объединившее математику и квантовую механику, обладающее разрушительной силой для основ нашего цифрового общества.&lt;/p>
&lt;p>RSA не устареет завтра, но в свете угроз вроде &amp;ldquo;Store Now, Decrypt Later&amp;rdquo;, масштабный переход криптографии к PQC уже начался. Мы являемся свидетелями смены парадигмы в информационной безопасности.&lt;/p></description></item><item><title>"Полная анатомия" понимания сильнейшего алгоритма криптоанализа "GNFS" путем его реализации на C++</title><link>http://kenji.blog/ru/p/gnfs-cpp-implementation/</link><pubDate>Sat, 05 Sep 2026 13:04:59 +0900</pubDate><guid>http://kenji.blog/ru/p/gnfs-cpp-implementation/</guid><description>&lt;img src="http://kenji.blog/p/gnfs-cpp-implementation/gnfs_cpp_blog_eyecatch_1788580949217.jpg" alt="Featured image of post "Полная анатомия" понимания сильнейшего алгоритма криптоанализа "GNFS" путем его реализации на C++" />&lt;h1 id="полная-анатомия-понимания-сильнейшего-алгоритма-криптоанализа-gnfs-путем-его-реализации-на-c">&amp;ldquo;Полная анатомия&amp;rdquo; понимания сильнейшего алгоритма криптоанализа &amp;ldquo;GNFS&amp;rdquo; путем его реализации на C++
&lt;/h1>&lt;p>«Шифрование RSA» фундаментально поддерживает современный Интернет. Его надежность опирается на математическое убеждение, что «факторизация огромного составного числа практически невозможна для современных компьютеров».&lt;/p>
&lt;p>Однако человечество никогда не сдается. В настоящее время существует ** самый сильный и передовой алгоритм ** человечества для гигантской факторизации на классических компьютерах (обычных, а не квантовых). Он называется ** &amp;ldquo;Общий метод решета числового поля&amp;rdquo; (GNFS: General Number Field Sieve) **.&lt;/p>
&lt;p>В этой статье мы полностью публикуем код реализации на C++ (с использованием целых чисел произвольной точности &lt;code>boost::multiprecision&lt;/code> библиотеки Boost), который строго моделирует эту передовую логику вычислений GNFS, и подробно объясняем стоящую за ней «алгебраическую теорию чисел».&lt;/p>
&lt;p>Пожалуйста, насладитесь тайнами математики и мощью информатики, которая их покоряет, вместе с исходным кодом.&lt;/p>
&lt;hr>
&lt;h2 id="1-логический-фреймворк-gnfs-полный-исходный-код">1. Логический фреймворк GNFS (полный исходный код)
&lt;/h2>&lt;p>Сначала представим всю картину реализации GNFS на C++, которая будет здесь объясняться. Фактический метод решета числового поля (например, CADO-NFS) — это гигантская распределенная система из сотен тысяч строк кода. Однако этот код извлекает ** «5 основных конвейеров (фаз)» **, составляющих GNFS, проектирует их как классы и строго моделирует в минимальной конфигурации без потери математического смысла.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt"> 10
&lt;/span>&lt;span class="lnt"> 11
&lt;/span>&lt;span class="lnt"> 12
&lt;/span>&lt;span class="lnt"> 13
&lt;/span>&lt;span class="lnt"> 14
&lt;/span>&lt;span class="lnt"> 15
&lt;/span>&lt;span class="lnt"> 16
&lt;/span>&lt;span class="lnt"> 17
&lt;/span>&lt;span class="lnt"> 18
&lt;/span>&lt;span class="lnt"> 19
&lt;/span>&lt;span class="lnt"> 20
&lt;/span>&lt;span class="lnt"> 21
&lt;/span>&lt;span class="lnt"> 22
&lt;/span>&lt;span class="lnt"> 23
&lt;/span>&lt;span class="lnt"> 24
&lt;/span>&lt;span class="lnt"> 25
&lt;/span>&lt;span class="lnt"> 26
&lt;/span>&lt;span class="lnt"> 27
&lt;/span>&lt;span class="lnt"> 28
&lt;/span>&lt;span class="lnt"> 29
&lt;/span>&lt;span class="lnt"> 30
&lt;/span>&lt;span class="lnt"> 31
&lt;/span>&lt;span class="lnt"> 32
&lt;/span>&lt;span class="lnt"> 33
&lt;/span>&lt;span class="lnt"> 34
&lt;/span>&lt;span class="lnt"> 35
&lt;/span>&lt;span class="lnt"> 36
&lt;/span>&lt;span class="lnt"> 37
&lt;/span>&lt;span class="lnt"> 38
&lt;/span>&lt;span class="lnt"> 39
&lt;/span>&lt;span class="lnt"> 40
&lt;/span>&lt;span class="lnt"> 41
&lt;/span>&lt;span class="lnt"> 42
&lt;/span>&lt;span class="lnt"> 43
&lt;/span>&lt;span class="lnt"> 44
&lt;/span>&lt;span class="lnt"> 45
&lt;/span>&lt;span class="lnt"> 46
&lt;/span>&lt;span class="lnt"> 47
&lt;/span>&lt;span class="lnt"> 48
&lt;/span>&lt;span class="lnt"> 49
&lt;/span>&lt;span class="lnt"> 50
&lt;/span>&lt;span class="lnt"> 51
&lt;/span>&lt;span class="lnt"> 52
&lt;/span>&lt;span class="lnt"> 53
&lt;/span>&lt;span class="lnt"> 54
&lt;/span>&lt;span class="lnt"> 55
&lt;/span>&lt;span class="lnt"> 56
&lt;/span>&lt;span class="lnt"> 57
&lt;/span>&lt;span class="lnt"> 58
&lt;/span>&lt;span class="lnt"> 59
&lt;/span>&lt;span class="lnt"> 60
&lt;/span>&lt;span class="lnt"> 61
&lt;/span>&lt;span class="lnt"> 62
&lt;/span>&lt;span class="lnt"> 63
&lt;/span>&lt;span class="lnt"> 64
&lt;/span>&lt;span class="lnt"> 65
&lt;/span>&lt;span class="lnt"> 66
&lt;/span>&lt;span class="lnt"> 67
&lt;/span>&lt;span class="lnt"> 68
&lt;/span>&lt;span class="lnt"> 69
&lt;/span>&lt;span class="lnt"> 70
&lt;/span>&lt;span class="lnt"> 71
&lt;/span>&lt;span class="lnt"> 72
&lt;/span>&lt;span class="lnt"> 73
&lt;/span>&lt;span class="lnt"> 74
&lt;/span>&lt;span class="lnt"> 75
&lt;/span>&lt;span class="lnt"> 76
&lt;/span>&lt;span class="lnt"> 77
&lt;/span>&lt;span class="lnt"> 78
&lt;/span>&lt;span class="lnt"> 79
&lt;/span>&lt;span class="lnt"> 80
&lt;/span>&lt;span class="lnt"> 81
&lt;/span>&lt;span class="lnt"> 82
&lt;/span>&lt;span class="lnt"> 83
&lt;/span>&lt;span class="lnt"> 84
&lt;/span>&lt;span class="lnt"> 85
&lt;/span>&lt;span class="lnt"> 86
&lt;/span>&lt;span class="lnt"> 87
&lt;/span>&lt;span class="lnt"> 88
&lt;/span>&lt;span class="lnt"> 89
&lt;/span>&lt;span class="lnt"> 90
&lt;/span>&lt;span class="lnt"> 91
&lt;/span>&lt;span class="lnt"> 92
&lt;/span>&lt;span class="lnt"> 93
&lt;/span>&lt;span class="lnt"> 94
&lt;/span>&lt;span class="lnt"> 95
&lt;/span>&lt;span class="lnt"> 96
&lt;/span>&lt;span class="lnt"> 97
&lt;/span>&lt;span class="lnt"> 98
&lt;/span>&lt;span class="lnt"> 99
&lt;/span>&lt;span class="lnt">100
&lt;/span>&lt;span class="lnt">101
&lt;/span>&lt;span class="lnt">102
&lt;/span>&lt;span class="lnt">103
&lt;/span>&lt;span class="lnt">104
&lt;/span>&lt;span class="lnt">105
&lt;/span>&lt;span class="lnt">106
&lt;/span>&lt;span class="lnt">107
&lt;/span>&lt;span class="lnt">108
&lt;/span>&lt;span class="lnt">109
&lt;/span>&lt;span class="lnt">110
&lt;/span>&lt;span class="lnt">111
&lt;/span>&lt;span class="lnt">112
&lt;/span>&lt;span class="lnt">113
&lt;/span>&lt;span class="lnt">114
&lt;/span>&lt;span class="lnt">115
&lt;/span>&lt;span class="lnt">116
&lt;/span>&lt;span class="lnt">117
&lt;/span>&lt;span class="lnt">118
&lt;/span>&lt;span class="lnt">119
&lt;/span>&lt;span class="lnt">120
&lt;/span>&lt;span class="lnt">121
&lt;/span>&lt;span class="lnt">122
&lt;/span>&lt;span class="lnt">123
&lt;/span>&lt;span class="lnt">124
&lt;/span>&lt;span class="lnt">125
&lt;/span>&lt;span class="lnt">126
&lt;/span>&lt;span class="lnt">127
&lt;/span>&lt;span class="lnt">128
&lt;/span>&lt;span class="lnt">129
&lt;/span>&lt;span class="lnt">130
&lt;/span>&lt;span class="lnt">131
&lt;/span>&lt;span class="lnt">132
&lt;/span>&lt;span class="lnt">133
&lt;/span>&lt;span class="lnt">134
&lt;/span>&lt;span class="lnt">135
&lt;/span>&lt;span class="lnt">136
&lt;/span>&lt;span class="lnt">137
&lt;/span>&lt;span class="lnt">138
&lt;/span>&lt;span class="lnt">139
&lt;/span>&lt;span class="lnt">140
&lt;/span>&lt;span class="lnt">141
&lt;/span>&lt;span class="lnt">142
&lt;/span>&lt;span class="lnt">143
&lt;/span>&lt;span class="lnt">144
&lt;/span>&lt;span class="lnt">145
&lt;/span>&lt;span class="lnt">146
&lt;/span>&lt;span class="lnt">147
&lt;/span>&lt;span class="lnt">148
&lt;/span>&lt;span class="lnt">149
&lt;/span>&lt;span class="lnt">150
&lt;/span>&lt;span class="lnt">151
&lt;/span>&lt;span class="lnt">152
&lt;/span>&lt;span class="lnt">153
&lt;/span>&lt;span class="lnt">154
&lt;/span>&lt;span class="lnt">155
&lt;/span>&lt;span class="lnt">156
&lt;/span>&lt;span class="lnt">157
&lt;/span>&lt;span class="lnt">158
&lt;/span>&lt;span class="lnt">159
&lt;/span>&lt;span class="lnt">160
&lt;/span>&lt;span class="lnt">161
&lt;/span>&lt;span class="lnt">162
&lt;/span>&lt;span class="lnt">163
&lt;/span>&lt;span class="lnt">164
&lt;/span>&lt;span class="lnt">165
&lt;/span>&lt;span class="lnt">166
&lt;/span>&lt;span class="lnt">167
&lt;/span>&lt;span class="lnt">168
&lt;/span>&lt;span class="lnt">169
&lt;/span>&lt;span class="lnt">170
&lt;/span>&lt;span class="lnt">171
&lt;/span>&lt;span class="lnt">172
&lt;/span>&lt;span class="lnt">173
&lt;/span>&lt;span class="lnt">174
&lt;/span>&lt;span class="lnt">175
&lt;/span>&lt;span class="lnt">176
&lt;/span>&lt;span class="lnt">177
&lt;/span>&lt;span class="lnt">178
&lt;/span>&lt;span class="lnt">179
&lt;/span>&lt;span class="lnt">180
&lt;/span>&lt;span class="lnt">181
&lt;/span>&lt;span class="lnt">182
&lt;/span>&lt;span class="lnt">183
&lt;/span>&lt;span class="lnt">184
&lt;/span>&lt;span class="lnt">185
&lt;/span>&lt;span class="lnt">186
&lt;/span>&lt;span class="lnt">187
&lt;/span>&lt;span class="lnt">188
&lt;/span>&lt;span class="lnt">189
&lt;/span>&lt;span class="lnt">190
&lt;/span>&lt;span class="lnt">191
&lt;/span>&lt;span class="lnt">192
&lt;/span>&lt;span class="lnt">193
&lt;/span>&lt;span class="lnt">194
&lt;/span>&lt;span class="lnt">195
&lt;/span>&lt;span class="lnt">196
&lt;/span>&lt;span class="lnt">197
&lt;/span>&lt;span class="lnt">198
&lt;/span>&lt;span class="lnt">199
&lt;/span>&lt;span class="lnt">200
&lt;/span>&lt;span class="lnt">201
&lt;/span>&lt;span class="lnt">202
&lt;/span>&lt;span class="lnt">203
&lt;/span>&lt;span class="lnt">204
&lt;/span>&lt;span class="lnt">205
&lt;/span>&lt;span class="lnt">206
&lt;/span>&lt;span class="lnt">207
&lt;/span>&lt;span class="lnt">208
&lt;/span>&lt;span class="lnt">209
&lt;/span>&lt;span class="lnt">210
&lt;/span>&lt;span class="lnt">211
&lt;/span>&lt;span class="lnt">212
&lt;/span>&lt;span class="lnt">213
&lt;/span>&lt;span class="lnt">214
&lt;/span>&lt;span class="lnt">215
&lt;/span>&lt;span class="lnt">216
&lt;/span>&lt;span class="lnt">217
&lt;/span>&lt;span class="lnt">218
&lt;/span>&lt;span class="lnt">219
&lt;/span>&lt;span class="lnt">220
&lt;/span>&lt;span class="lnt">221
&lt;/span>&lt;span class="lnt">222
&lt;/span>&lt;span class="lnt">223
&lt;/span>&lt;span class="lnt">224
&lt;/span>&lt;span class="lnt">225
&lt;/span>&lt;span class="lnt">226
&lt;/span>&lt;span class="lnt">227
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;vector&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;cmath&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;map&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;set&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;chrono&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;boost/multiprecision/cpp_int.hpp&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Использование чисел произвольной точности Boost.Multiprecision
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">using&lt;/span> &lt;span class="k">namespace&lt;/span> &lt;span class="n">boost&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">multiprecision&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// [SOTA GNFS] General Number Field Sieve Передовой логический фреймворк
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">//
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Этот код строго моделирует 5 конвейеров современного GNFS,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// используемого в CADO-NFS и др., как классы на C++ (Boost).
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">struct&lt;/span> &lt;span class="nc">Relation&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int64_t&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int64_t&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">uint32_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">rational_primes&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">uint32_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">algebraic_primes&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Фаза 1: Выбор полинома (алгоритм КлейнЮнга)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">class&lt;/span> &lt;span class="nc">PolynomialSelector&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span> &lt;span class="n">degree&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">cpp_int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Алгебраический полином f(x)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">cpp_int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">g&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Рациональный полином g(x) = x - m
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">PolynomialSelector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">d&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">degree&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">d&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Генерация начального полинома на основе m-расширения (в реальности используется более сложное сокращение базиса решетки LLL)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">cpp_int&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Фаза 1] Выбор полинома (Степень &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">degree&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;) начинается...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Простое m-расширение (степени d)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// m = N^(1/d)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">N_copy&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">m&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Простая аппроксимация m (без использования функций Boost)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">low&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">high&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">low&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">high&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">mid&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">low&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">high&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">low&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">degree&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">p&lt;/span> &lt;span class="o">*=&lt;/span> &lt;span class="n">mid&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">p&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mid&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">low&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mid&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">high&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">mid&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">resize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">degree&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">temp&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">degree&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">temp&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">temp&lt;/span> &lt;span class="o">/=&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">m&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">};&lt;/span> &lt;span class="c1">// g(x) = x - m
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; -&amp;gt; m = &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">m&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; -&amp;gt; f(x) = &amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">degree&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">--&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;x^&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="s">&amp;#34; + &amp;#34;&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">[Фаза 1] Завершено.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Фаза 2: Решето на решетках (Lattice Sieving)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// В современных GNFS вместо Line Sieve используется Special-q Lattice Sieving,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// разработанное Франке и КлейнЮнгом, которое стало де-факто стандартом.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">class&lt;/span> &lt;span class="nc">LatticeSieve&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">uint32_t&lt;/span> &lt;span class="n">rational_bound&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">uint32_t&lt;/span> &lt;span class="n">algebraic_bound&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">uint32_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">rational_fb&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">uint32_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">algebraic_fb&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">LatticeSieve&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">uint32_t&lt;/span> &lt;span class="n">rb&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">uint32_t&lt;/span> &lt;span class="n">ab&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">rational_bound&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">rb&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">algebraic_bound&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ab&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="nf">generate_factor_bases&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Фаза 2] Генерация факторных баз (Рациональная граница: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">rational_bound&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;, Алгебраическая граница: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">algebraic_bound&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;)&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// (Опущено) На самом деле выполняется генерация простых чисел и фильтрация с помощью символов Лежандра и т.д.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">sieve&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">PolynomialSelector&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">poly&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Фаза 2] Special-q Lattice Sieving активен...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Макетная реализация: реальное решето на решетках сканирует сотни ГБ памяти блоками.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// Пары (a, b) проецируются на решетку (a = i*q + j*...) для каждого особого простого q,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// и выполняется просеивание с экстремальной эффективностью кэширования.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Добавлено фиктивное отношение для демонстрации
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Relation&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">17&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">r&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">rational_primes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">r&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">algebraic_primes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">relations&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push_back&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Фаза 2] Найдено &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">size&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; отношений.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Фаза 3: Фильтрация (удаление синглтонов и слияние клик)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">class&lt;/span> &lt;span class="nc">Filter&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="n">reduce_matrix&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&amp;amp;&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Фаза 3] Фильтрация отношений...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 1. Удаление синглтонов (удаление отношений с простыми числами, появляющимися только раз)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 2. Слияние клик (объединение отношений для превращения разреженной матрицы в плотную)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// В реальности алгоритмы вроде Union-Find сжимают матрицу из сотен миллионов строк до нескольких миллионов.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Фаза 3] Размер матрицы оптимально уменьшен.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Фаза 4: Линейная алгебра над GF(2) (метод Блока Видемана)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">class&lt;/span> &lt;span class="nc">LinearAlgebraGF2&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// В современных суперкомпьютерных средах вместо метода Block Lanczos
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// передовым является метод Block Wiedemann (реализация Coppersmith), удобный для распределенных вычислений.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">solve_nullspace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&amp;amp;&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Фаза 4] Алгоритм Блока Видемана над GF(2) начинается...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Итеративное вычисление произведения разреженной матрицы и вектора,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// поиск нескольких векторов решений (ядер), где M * x = 0 mod 2.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">dependencies&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Список зависимостей
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// Фиктивные данные
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">dependencies&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push_back&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Фаза 4] Найдено &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">dependencies&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">size&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; линейных зависимостей (полных квадратов).&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">dependencies&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Фаза 5: Алгебраический квадратный корень (Algebraic Square Root)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">class&lt;/span> &lt;span class="nc">AlgebraicSquareRoot&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="n">compute_and_factor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&amp;amp;&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&amp;amp;&lt;/span> &lt;span class="n">dep&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="n">cpp_int&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Фаза 5] Вычисление алгебраического квадратного корня...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 1. Вычисление рационального корня V
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">V&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// V = sqrt( prod(a - bm) ) mod N
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 2. Вычисление алгебраического корня gamma (методом Монтгомери и др.)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// Нахождение элемент gamma в огромном алгебраическом поле O_K и его отображение в реальный мир гомоморфизмом phi
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// Y = phi(gamma) mod N
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">Y&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Предполагается, что в Фазах 2 и 4 были добавлены столбцы квадратичных характеров (Quadratic Characters)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// во избежание препятствий группы классов идеалов и группы единиц.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; -&amp;gt; Гомоморфизм phi применен.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[Фаза 5] Вычисление НОД(V - Y, N)...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">factor&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">V&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">Y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// НОД(X-Y, N)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">factor&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">factor&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">================================================================&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[УСПЕХ] Найден нетривиальный множитель: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">factor&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; Другой множитель: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">N&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">factor&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;================================================================&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;[НЕУДАЧА] Тривиальное решение. Пробуем следующую зависимость...&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Основной конвейер выполнения
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// ============================================================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;================================================================&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; [SOTA GNFS] Движок General Number Field Sieve (Boost C++) &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;================================================================&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Гигантское составное число N (например, RSA-270)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;233108530344407544527637656910680524145619812480305449042948611968495918245135782867888369318577116418213919268572658314913060672626911354027609793166341626693946596196427744273886601876896313468704059066746903123910748277606548649151920812699309766587514735456594993207&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Степень полинома (для &amp;gt; 130 цифр обычно выбирают 5-6)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">degree&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">6&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Инициализация конвейера
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">PolynomialSelector&lt;/span> &lt;span class="n">poly_select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">degree&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">LatticeSieve&lt;/span> &lt;span class="n">sieve&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">10000000&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">20000000&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// Реальные границы составляют миллионы
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Filter&lt;/span> &lt;span class="n">filter&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">LinearAlgebraGF2&lt;/span> &lt;span class="n">linalg&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">AlgebraicSquareRoot&lt;/span> &lt;span class="n">sqrt_step&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">auto&lt;/span> &lt;span class="n">start_time&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">chrono&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">high_resolution_clock&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 1. Выбор полинома
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">poly_select&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">N&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 2. Просеивание (sieve)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">sieve&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">generate_factor_bases&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">relations&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sieve&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">sieve&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">poly_select&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 3. Фильтрация (сжатие матрицы)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">filter&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">reduce_matrix&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">relations&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 4. Линейная алгебра (Поиск нуль-пространства над GF(2))
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">dependencies&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">linalg&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">solve_nullspace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">relations&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 5. Вычисление алгебраического квадратного корня и НОД
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="k">auto&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="nl">dep&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">dependencies&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sqrt_step&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">compute_and_factor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">relations&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dep&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">auto&lt;/span> &lt;span class="n">end_time&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">chrono&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">high_resolution_clock&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">chrono&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">duration&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">double&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">elapsed&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">end_time&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">start_time&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">[Система] Конвейер SOTA GNFS завершен за &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">elapsed&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">count&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34; секунд.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Итак, как этот код разрушает криптографические стены? Давайте разберем тщательный алгоритм и высшую математику каждой из 5 фаз.&lt;/p>
&lt;hr>
&lt;h2 id="2-конечная-цель-gnfs-x2-equiv-y2-pmod-n">2. Конечная цель GNFS: $X^2 \equiv Y^2 \pmod N$
&lt;/h2>&lt;p>Как и в случае GNFS, большинство современных алгоритмов факторизации гигантских чисел стремятся найти нетривиальную пару $(X, Y)$, удовлетворяющую следующему сравнению:&lt;/p>
$$X^2 \equiv Y^2 \pmod N$$
&lt;p>Это означает, что «остаток от деления $X^2$ и $Y^2$ на $N$ одинаков». Преобразовав это, получим:
$X^2 - Y^2 \equiv 0 \pmod N$
Другими словами, $(X-Y)(X+Y)$ кратно $N$.&lt;/p>
&lt;p>Если $X \not\equiv \pm Y \pmod N$ (нетривиальное решение), это означает, что между $(X-Y)$ и $N$ есть «общий делитель больше 1 и меньше $N$».
Если мы воспользуемся алгоритмом Евклида для вычисления ** $\gcd(X-Y, N)$ **, то легко найдем простой множитель $N$.&lt;/p>
&lt;p>Однако поиск этих $X$ и $Y$ сродни поиску иголки в пустыне. Поэтому GNFS применяет гениальный подход: создает ** два мира ** — «мир реальных целых чисел» и «мир алгебраических числовых полей полиномов» — для распределения вычислений.&lt;/p>
&lt;hr>
&lt;h2 id="3-фаза-1-выбор-полинома-polynomial-selection">3. Фаза 1: Выбор полинома (Polynomial Selection)
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">PolynomialSelector&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">cpp_int&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// вычисление m = N^(1/d) и m-расширение
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">degree&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">temp&lt;/span> &lt;span class="o">%&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">temp&lt;/span> &lt;span class="o">/=&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">g&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">m&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">};&lt;/span> &lt;span class="c1">// g(x) = x - m
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Первый шаг GNFS — создание «магического полинома», связывающего оба мира.
Для гигантского числа $N$ выбираем целое $m$. Обычно так, чтобы $m \approx N^{1/d}$ (в коде предполагается полином степени $d=6$).&lt;/p>
&lt;p>Затем мы разлагаем $N$ по основанию $m$ и используем его коэффициенты для построения полинома $f(x)$:
&lt;/p>
$$N = c_d m^d + c_{d-1} m^{d-1} + \dots + c_1 m + c_0$$
$$f(x) = c_d x^d + c_{d-1} x^{d-1} + \dots + c_1 x + c_0$$
&lt;p>Этот полином $f(x)$ обладает крайне важным свойством: ** «если подставить $m$ в переменную $x$, получится ровно $N$ ($f(m) = N$)» **. То есть $f(m) \equiv 0 \pmod N$.
Рациональный полином определяется как $g(x) = x - m$.&lt;/p>
&lt;p>В результате ** «мир алгебраического поля $\mathbb{Z}[\alpha]$» **, управляемый корнем $\alpha$ из $f(x)=0$, и обычный ** «мир рациональных чисел (целых) $\mathbb{Z}$» ** прочно связываются «гомоморфизмом колец» $x \to m$.&lt;/p>
&lt;p>В современных CADO-NFS и других реализациях используются алгоритмы КлейнЮнга и алгоритм LLL-редукции базиса решетки для поиска «самого удобного полинома $f(x)$», при котором коэффициенты не становятся чрезмерно большими, а простые числа легче появляются на следующих этапах. Этот поиск может занимать месяцы.&lt;/p>
&lt;hr>
&lt;h2 id="4-фаза-2-решето-на-специальной-q-решетке-special-q-lattice-sieving">4. Фаза 2: Решето на специальной q-решетке (Special-q Lattice Sieving)
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">LatticeSieve&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">sieve&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">PolynomialSelector&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">poly&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// Пары (a, b) проецируются на решетку для каждого особого простого q,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// и выполняется просеивание, максимизирующее эффективность кэширования.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Подготовив оба мира, мы переходим к поиску «гладких чисел (состоящих только из маленьких простых множителей)» в обоих мирах.
Генерируются бесчисленные пары целых чисел $(a, b)$ и вычисляются два значения:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Рациональное значение&lt;/strong> : $a - bm$&lt;/li>
&lt;li>&lt;strong>Алгебраическая норма&lt;/strong> : $b^d f(a/b)$&lt;/li>
&lt;/ol>
&lt;p>Цель GNFS состоит в том, чтобы собрать от десятков до сотен миллионов ** «пар (отношений), в которых и рациональное, и алгебраическое значения могут быть полностью факторизованы только малыми простыми множителями» **.&lt;/p>
&lt;p>В раннем GNFS использовалось «Линейное решето (Line Sieve)», где $(a, b)$ располагались на плоскости $xy$ и делились на простые числа. Но это было крайне медленно из-за промахов кэша при частом обращении к памяти.&lt;/p>
&lt;p>Поэтому современные коды используют метод, называемый ** &amp;ldquo;Special-q Lattice Sieve&amp;rdquo; **.
Фиксируется достаточно большое простое число $q$, и вычисляются только пары $(a, b)$, где «алгебраическое значение гарантированно делится на $q$». Пары, удовлетворяющие этому условию, образуют «решетку (Lattice)» на плоскости, делая скачки адресов в памяти постоянными, что идеально вписывается в кэш L1/L2 процессора.
Введение решета на решетках резко повысило скорость вычислений GNFS.&lt;/p>
&lt;hr>
&lt;h2 id="5-фаза-3-фильтрация-filtering">5. Фаза 3: Фильтрация (Filtering)
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">Filter&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="n">reduce_matrix&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&amp;amp;&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 1. Удаление синглтонов (удаление отношений с простыми числами, появляющимися только 1 раз)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 2. Слияние клик (объединение отношений для уплотнения разреженной матрицы)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Сотни миллионов отношений, собранных компьютерами по всему миру за несколько месяцев на Фазе 2. Однако, если их сразу передать на следующий этап «вычисления матрицы», память суперкомпьютера переполнится.&lt;/p>
&lt;p>Следовательно, происходит экстремальный процесс сжатия матрицы, называемый ** Фильтрацией (Filtering) **.&lt;/p>
&lt;ol>
&lt;li>
&lt;p>&lt;strong>Удаление синглтонов (Singleton removal)&lt;/strong>
Предположим, гигантское простое число $p$ встречается только «1 раз» во всех миллионах отношений. Наша цель — «сделать показатели всех простых чисел четными (кратными 2)», так что простое число, появляющееся лишь однажды, не может стать четным.
Поэтому отношения, содержащие такое простое число, немедленно удаляются как «бесполезный мусор». Это вызывает цепную реакцию, убирая миллионы строк данных.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Слияние клик (Clique merging)&lt;/strong>
Далее, путем сложения отношений, разделяющих определенные простые числа, разреженная матрица сжимается и становится более плотной (используя метод, подобный поиску клик в теории графов).&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>Благодаря этой оптимизации, гигантская разреженная матрица радикально сжимается до вычислимых размеров.&lt;/p>
&lt;hr>
&lt;h2 id="6-фаза-4-линейная-алгебра-над-gf2-метод-блока-видемана">6. Фаза 4: Линейная алгебра над GF(2) (метод Блока Видемана)
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">LinearAlgebraGF2&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">solve_nullspace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Relation&lt;/span>&lt;span class="o">&amp;gt;&amp;amp;&lt;/span> &lt;span class="n">relations&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Итеративное вычисление произведения разреженной матрицы и вектора,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// поиск решений (ядер), где M * x = 0 mod 2.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Теперь мы подходим к сути головоломки.
Мы объединяем собранные отношения для поиска ** «комбинаций, в которых степени всех простых множителей становятся четными» **.&lt;/p>
&lt;p>Математически, используя гигантскую матрицу $M$, элементы которой представляют собой «четность или нечетность (т.е. 0 или 1)» степени каждого простого числа, и вектор $x$, показывающий, какие отношения используются, мы решаем уравнение (поиск нуль-пространства):
&lt;strong>$M \cdot x \equiv 0 \pmod 2$&lt;/strong>&lt;/p>
&lt;p>Нам нужно решить систему уравнений матрицы размером миллионы на миллионы строк и столбцов. При обычном методе Гаусса сложность составляет $O(N^3)$, и вычисления не закончатся до конца Вселенной.&lt;/p>
&lt;p>Поэтому современные реализации применяют ** «Метод Блока Видемана (Block Wiedemann)» **.
Это вид метода подпространства Крылова, который находит решение путем итеративного умножения матрицы на вектор, эксплуатируя то, что матрица $M$ «очень разреженная (почти все 0)».
В отличие от старого метода Block Lanczos, метод Block Wiedemann полностью разделяет вычислительный процесс на кластеры, демонстрируя огромную мощь в современных распределенных облачных вычислениях и на суперкомпьютерах.&lt;/p>
&lt;hr>
&lt;h2 id="7-фаза-5-алгебраический-квадратный-корень-algebraic-square-root-и-крушение-криптографии">7. Фаза 5: Алгебраический квадратный корень (Algebraic Square Root) и крушение криптографии
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">AlgebraicSquareRoot&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="n">compute_and_factor&lt;/span>&lt;span class="p">(...)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 1. Вычисление рационального квадратного корня V
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">V&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 2. Вычисление алгебраического корня gamma
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">Y&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">cpp_int&lt;/span> &lt;span class="n">factor&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gcd&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">V&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">Y&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">N&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// GCD(X-Y, N)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Через вычисления матрицы на Фазе 4 мы получили набор отношений $S$, которые «при перемножении дают четные степени для всех простых множителей».
Это позволяет нам создать «квадрат» в обоих мирах — рациональном и алгебраическом.&lt;/p>
&lt;p>Поскольку рациональная сторона — это просто умножение целых чисел, вычислить квадратный корень $V$ легко.
&lt;/p>
$$V^2 = \prod_{S} (a - bm)$$
&lt;p>&lt;strong>Но настоящий ад ждет на «алгебраической стороне».&lt;/strong>
В мире алгебраических полей $\mathbb{Z}[\alpha]$ уникальность факторизации на простые не сохраняется, поэтому мы вычисляли, используя идеалы. Расчеты матрицы гарантировали лишь ** «создание квадрата идеала», но не «гарантировали, что это квадрат элемента ($\gamma^2$)» **.&lt;/p>
&lt;p>Здесь возникают грозные барьеры алгебраической теории чисел — «препятствие группы классов идеалов» и «препятствие группы единиц».
Чтобы преодолеть эту стену, GNFS использует магию ** «Квадратичных характеров (Quadratic Characters)» **.
В матрицу Фазы 4 заранее добавляются несколько десятков специальных столбцов квадратичных вычетов (символов Лежандра) для особых простых идеалов. В результате найденный набор $S$ с ошеломляющей вероятностью обходит все препятствия и благополучно формирует «истинный квадрат элемента $\gamma^2$».&lt;/p>
&lt;p>Процесс нахождения $\gamma$ (Алгебраический квадратный корень) выполняется с помощью невероятно сложного алгоритма, такого как метод Монтгомери.&lt;/p>
&lt;p>И, наконец, алгебраический корень $\gamma$ переносится в реальный мир с помощью гомоморфизма колец $\phi$ (подстановка $m$ вместо $x$), образуя $Y$.
Установив $V$ с рациональной стороны как $X$, мы получаем абсолютное уравнение, к которому стремились:&lt;/p>
&lt;p>&lt;strong>$$X^2 \equiv Y^2 \pmod N$$&lt;/strong>&lt;/p>
&lt;p>Остается только вычислить $\gcd(X-Y, N)$. За долю секунды 0,001 с нетривиальный множитель выводится на экран, и гордая, неприступная криптография RSA полностью рушится.&lt;/p>
&lt;hr>
&lt;h2 id="заключение">Заключение
&lt;/h2>&lt;p>GNFS — это не просто метод программирования.
Это шедевр человеческого интеллекта, который покорил «глубины чистой математики», такие как абстрактная алгебра, теория колец и группы классов идеалов, с помощью «экстремальной инженерии» — распределенной архитектуры суперкомпьютеров и кэш-оптимизации.&lt;/p>
&lt;p>Наши повседневные сообщения в чатах или данные кредитных карт защищены именно этими колоссальными математическими битвами.&lt;/p>
&lt;p>Мы надеемся, что этот фреймворк на C++ позволил вам почувствовать «романтику математики и компьютеров», стоящую за передовыми алгоритмами криптоанализа.&lt;/p></description></item><item><title>Истинная математическая структура общего метода решета числового поля (GNFS)</title><link>http://kenji.blog/ru/p/%E4%B8%80%E8%88%AC%E6%95%B0%E4%BD%93%E7%AF%A9%E6%B3%95gnfs%E3%81%AE%E7%9C%9F%E3%81%AE%E6%95%B0%E5%AD%A6%E7%9A%84%E6%A7%8B%E9%80%A0/</link><pubDate>Sat, 05 Sep 2026 02:26:13 +0900</pubDate><guid>http://kenji.blog/ru/p/%E4%B8%80%E8%88%AC%E6%95%B0%E4%BD%93%E7%AF%A9%E6%B3%95gnfs%E3%81%AE%E7%9C%9F%E3%81%AE%E6%95%B0%E5%AD%A6%E7%9A%84%E6%A7%8B%E9%80%A0/</guid><description>&lt;img src="http://kenji.blog/p/%E4%B8%80%E8%88%AC%E6%95%B0%E4%BD%93%E7%AF%A9%E6%B3%95gnfs%E3%81%AE%E7%9C%9F%E3%81%AE%E6%95%B0%E5%AD%A6%E7%9A%84%E6%A7%8B%E9%80%A0/rsa_encryption_break_1788542156523.jpg" alt="Featured image of post Истинная математическая структура общего метода решета числового поля (GNFS)" />&lt;h1 id="истинная-математическая-структура-общего-метода-решета-числового-поля-gnfs">Истинная математическая структура общего метода решета числового поля (GNFS)
&lt;/h1>&lt;p>Конечная цель GNFS — найти $X, Y$ такие, что $X^2 \equiv Y^2 \pmod N$.
Для достижения этого математики построили мост между &lt;strong>&amp;ldquo;миром реальных целых чисел&amp;rdquo;&lt;/strong> и &lt;strong>&amp;ldquo;миром алгебраических полей&amp;rdquo;&lt;/strong>. Этим мостом является «гомоморфизм».&lt;/p>
&lt;h2 id="этап-1-гомоморфизм-homomorphism-соединяющий-миры">Этап 1: «Гомоморфизм» (Homomorphism), соединяющий миры
&lt;/h2>&lt;h3 id="1-выбор-многочлена-и-определение-корня">1. Выбор многочлена и определение корня
&lt;/h3>&lt;p>Для гигантского составного числа $N$ мы выбираем некоторое целое число $m$ и многочлен $f(x)$ так, чтобы $f(m) \equiv 0 \pmod N$.
(Пример: Разложите $N$ по основанию $m$ и постройте $f(x)$ из его коэффициентов. При этом предполагается, что $f(x)$ неприводим над полем рациональных чисел $\mathbb{Q}$).&lt;/p>
&lt;p>Далее, пусть $\alpha$ — один из «комплексных корней» уравнения $f(x) = 0$.
Естественно, $f(\alpha) = 0$. $\alpha$ — это не целое число, а сложное число (алгебраическое число), которое может содержать корни или мнимые единицы.&lt;/p>
&lt;h3 id="2-построение-кольца-ring-и-гомоморфизма">2. Построение кольца (Ring) и гомоморфизма
&lt;/h3>&lt;p>Здесь мы подготавливаем два математических «кольца» (миры, где определены сложение и умножение):&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Мир A: $\mathbb{Z}[\alpha]$&lt;/strong> (Кольцо алгебраических целых чисел, содержащее $\alpha$)
Это мир чисел, выраженных в виде $a + b\alpha + c\alpha^2 + \dots$.&lt;/li>
&lt;li>&lt;strong>Мир B: $\mathbb{Z}/N\mathbb{Z}$&lt;/strong> (Кольцо вычетов по модулю $N$)
Мир сравнений (по модулю), состоящий только из целых чисел от $0$ до $N-1$.&lt;/li>
&lt;/ul>
&lt;p>Здесь мы определяем отображение (mapping) $\phi$ из Мира A в Мир B следующим образом:
&lt;strong>$$\phi : \mathbb{Z}[\alpha] \to \mathbb{Z}/N\mathbb{Z}$$&lt;/strong>
&lt;strong>$$\phi(\alpha) = m \pmod N$$&lt;/strong>&lt;/p>
&lt;p>Это отображение $\phi$ — магическая операция, которая полностью заменяет переменную $\alpha$ в Мире A на целое число $m$ в Мире B.
Это $\phi$ обладает чрезвычайно мощным свойством, называемым &lt;strong>&amp;ldquo;Гомоморфизм колец&amp;rdquo; (Ring Homomorphism)&lt;/strong>.
Гомоморфизм — это свойство &lt;strong>&amp;ldquo;перехода в другой мир без разрушения структуры сложения и умножения&amp;rdquo;&lt;/strong>. То есть выполняются следующие уравнения:&lt;/p>
&lt;ul>
&lt;li>$\phi(X \times Y) = \phi(X) \times \phi(Y)$&lt;/li>
&lt;li>$\phi(X^2) = \phi(X)^2$&lt;/li>
&lt;/ul>
&lt;p>Что все это значит? Если мы сможем создать &lt;strong>&amp;ldquo;полный квадрат&amp;rdquo; ($\gamma^2$)&lt;/strong> из сложного элемента $\gamma$ в &amp;ldquo;Мире A&amp;rdquo; (мире $\alpha$), мы сможем прыгнуть в &amp;ldquo;Мир B&amp;rdquo; (мир остатков) с помощью $\phi$, и &lt;strong>форма квадрата $\phi(\gamma)^2$ будет идеально сохранена&lt;/strong>.&lt;/p>
&lt;hr>
&lt;h2 id="этап-2-крах-разложения-на-простые-множители-и-рождение-идеала-ideal">Этап 2: Крах разложения на простые множители и рождение «Идеала» (Ideal)
&lt;/h2>&lt;p>Мы хотим собрать множество подходящих элементов $(a - b\alpha)$ в Мире A ($\mathbb{Z}[\alpha]$) и перемножить их, чтобы получить «полный квадрат» (квадратичный элемент).
Обычно мы могли бы разложить собранные $(a - b\alpha)$ на «простые множители» и объединить их так, чтобы все показатели степеней простых чисел стали четными (решается с помощью матриц), создавая таким образом квадрат.&lt;/p>
&lt;p>&lt;strong>Однако здесь на пути встает стена алгебраического отчаяния.&lt;/strong>
В мире алгебраических полей, таких как $\mathbb{Z}[\alpha]$, &lt;strong>&amp;ldquo;уникальность разложения на простые множители (каждое число может быть представлено как произведение простых чисел только одним способом)&amp;rdquo;&lt;/strong>, которую мы изучали в средней школе, &lt;strong>полностью рушится&lt;/strong>.&lt;/p>
&lt;p>(Пример: В некоторых мирах алгебраических полей $6 = 2 \times 3$, и в то же время $6 = (1+\sqrt{-5}) \times (1-\sqrt{-5})$, что делает невозможным узнать, какие из них являются истинными простыми числами).&lt;/p>
&lt;p>Если разложение на простые множители не уникально, то головоломка &amp;ldquo;подсчета простых чисел до тех пор, пока их не станет четное количество&amp;rdquo; (метод решета) принципиально невыполнима.&lt;/p>
&lt;h3 id="спасение-куммера-и-дедекинда-идеал">Спасение Куммера и Дедекинда: «Идеал»
&lt;/h3>&lt;p>Этот крах был спасен концепцией &lt;strong>&amp;ldquo;Идеала&amp;rdquo; (Ideal: Идеальное число)&lt;/strong>, созданной математиками 19 века.
Вместо того чтобы рассматривать сам элемент, рассматривая &amp;ldquo;множество кратных (идеал)&amp;rdquo;, порожденное этим элементом, разложение на простые множители снова стало возможным.&lt;/p>
&lt;p>В кольце целых чисел алгебраического поля $\mathcal{O}_K$ (более совершенном кольце, включающем $\mathbb{Z}[\alpha]$), даже если элементы не могут быть однозначно разложены на множители, доказано, что &lt;strong>&amp;ldquo;Идеал всегда может быть однозначно разложен на простые множители как произведение &amp;lsquo;простых идеалов&amp;rsquo; ($\mathfrak{p}$)&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;p>Поэтому в GNFS вместо разложения самого элемента $(a - b\alpha)$ мы выполняем &lt;strong>разложение на простые идеалы главного идеала $\langle a - b\alpha \rangle$&lt;/strong>, который он порождает.&lt;/p>
&lt;hr>
&lt;h2 id="этап-3-норма-norm-и-два-решета-sieve">Этап 3: Норма (Norm) и два решета (Sieve)
&lt;/h2>&lt;p>Тогда как нам узнать, на какие простые идеалы распадается идеал $\langle a - b\alpha \rangle$?
Здесь мы используем функцию, называемую &lt;strong>&amp;ldquo;Норма&amp;rdquo; (Norm)&lt;/strong>. Норма — это функция, которая преобразует сложные элементы алгебраического поля в &amp;ldquo;обычные целые числа $\mathbb{Z}$&amp;rdquo; реального мира.&lt;/p>
&lt;p>Норма элемента $(a - b\alpha)$ вычисляется с помощью простого многочлена $b^d f(a/b)$ (где $d$ — степень $f(x)$).&lt;/p>
&lt;p>Благодаря алгебраической теореме известно, что &lt;strong>&amp;ldquo;если норма идеала может быть полностью разложена на небольшие простые числа (является гладкой), то исходный идеал также может быть полностью разложен на небольшие простые идеалы&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;p>Поэтому GNFS одновременно вычисляет следующие две вещи для огромного количества пар целых чисел $(a, b)$ и собирает только те пары, где обе являются &amp;ldquo;гладкими числами&amp;rdquo;:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Рациональное решето (Rational Sieve)&lt;/strong>: $a - bm$ (значение в реальном мире)&lt;/li>
&lt;li>&lt;strong>Алгебраическое решето (Algebraic Sieve)&lt;/strong>: $b^d f(a/b)$ (норма в мире алгебраического поля)&lt;/li>
&lt;/ol>
&lt;p>Мы собираем десятки миллионов пар $(a, b)$, обе из которых гладкие, решаем данные о разложении идеалов на простые множители (сколько простых идеалов присутствует) в виде гигантской матрицы (линейная алгебра над GF(2)) и находим множество $S$ пар таких, что &amp;ldquo;при перемножении показатели всех простых идеалов становятся четными&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h2 id="этап-4-два-препятствия-и-группа-классов-идеалов">Этап 4: Два «Препятствия» и группа классов идеалов
&lt;/h2>&lt;p>С помощью матричных вычислений мы обнаружили, что умножение всех идеалов $(a - b\alpha)$ во множестве $S$ дает квадрат некоторого идеала $I$.
&lt;/p>
$$\prod_{S} \langle a - b\alpha \rangle = I^2$$
&lt;p>&lt;strong>Но это еще не конец. Самая глубокая и трудная математическая стена в GNFS находится здесь.&lt;/strong>&lt;/p>
&lt;p>В конечном итоге нам нужен не &amp;ldquo;квадрат идеала&amp;rdquo;, а &lt;strong>&amp;ldquo;квадрат элемента&amp;rdquo; ($\gamma^2$)&lt;/strong> для подстановки в отображение $\phi$.
Только потому, что идеал возведен в квадрат, не означает, что сам элемент возведен в квадрат. Здесь существуют &lt;strong>два невероятно сильных математических препятствия (Obstructions)&lt;/strong>.&lt;/p>
&lt;h3 id="препятствие-1-стена-группы-классов-идеалов-ideal-class-group">Препятствие 1: Стена группы классов идеалов (Ideal Class Group)
&lt;/h3>&lt;p>Идеал $I$ не всегда является &amp;ldquo;идеалом, порожденным одним элементом (главным идеалом)&amp;rdquo;.
Невозможно извлечь конкретный элемент $\gamma$ из идеала, который не является главным.&lt;/p>
&lt;p>Здесь появляется концепция &lt;strong>&amp;ldquo;Группы классов идеалов (Class Group, $Cl_K$)&amp;rdquo;&lt;/strong>. Группа классов идеалов — это группа, которая измеряет, &amp;ldquo;сколько неглавных идеалов существует в мире алгебраического поля (насколько разрушена уникальность разложения на простые множители)&amp;rdquo;.
Даже если $\prod \langle a - b\alpha \rangle$ становится $I^2$, если $I$ не является единичным элементом (главным идеалом) в группе классов идеалов, мы не можем вернуть его к квадрату элемента.&lt;/p>
&lt;h3 id="препятствие-2-стена-группы-единиц-unit-group">Препятствие 2: Стена группы единиц (Unit Group)
&lt;/h3>&lt;p>Допустим, нам повезло, и $I$ является главным идеалом $\langle \gamma \rangle$.
Тогда $\prod \langle a - b\alpha \rangle = \langle \gamma^2 \rangle$.
Вы можете подумать: &amp;ldquo;Отлично, элемент тоже в квадрате!&amp;rdquo;, но вы глубоко ошибаетесь.&lt;/p>
&lt;p>Тот факт, что идеалы (множества кратных) равны, не означает, что элементы полностью равны. Всегда будет сдвиг на &lt;strong>&amp;ldquo;Единицу&amp;rdquo; (Unit: число, обратное которому также является целым, например 1 или -1)&lt;/strong>.
Другими словами, фактическое равенство элементов выглядит следующим образом:
&lt;/p>
$$\prod_{S} (a - b\alpha) = u \cdot \gamma^2$$
&lt;p>
(где $u$ — элемент группы единиц $U_K$)&lt;/p>
&lt;p>Если только эта единица $u$ сама не является квадратом чего-либо (квадратичным элементом), левая часть никогда не сможет стать &amp;ldquo;идеальным квадратом элемента&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h2 id="этап-5-магия-адлемана-квадратичные-характеры-quadratic-characters">Этап 5: Магия Адлемана «Квадратичные характеры» (Quadratic Characters)
&lt;/h2>&lt;p>Препятствие группы классов идеалов и препятствие группы единиц. Как нам их преодолеть?
Здесь появляется гениальный метод, называемый &lt;strong>&amp;ldquo;Квадратичными характерами&amp;rdquo; (Quadratic Characters)&lt;/strong>, введенный криптографом Леонардом Адлеманом (буква &amp;ldquo;A&amp;rdquo; в RSA) и его коллегами.&lt;/p>
&lt;p>Чтобы определить, &amp;ldquo;является ли элемент полным квадратом в алгебраическом поле&amp;rdquo;, мы используем версию символа Лежандра (квадратичного вычета) для алгебраических полей.
В гигантскую матрицу (головоломку для того, чтобы сделать количество простых идеалов четным) мы тайно добавляем несколько десятков дополнительных условий (столбцов), утверждающих, что &lt;strong>&amp;ldquo;квадратичные характеры для некоторых особых простых идеалов $\mathfrak{q}$ также все становятся равными $1$ (четными)&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;p>Когда мы находим множество $S$, удовлетворяющее этим дополнительным условиям с помощью матричных вычислений, глубокая теорема алгебраической теории чисел гарантирует, что &lt;strong>&amp;ldquo;как препятствие группы классов идеалов, так и препятствие группы единиц исчезнут естественным образом с подавляющей вероятностью&amp;rdquo;&lt;/strong>.&lt;/p>
&lt;p>Благодаря этому мы наконец получаем истинное уравнение:
&lt;/p>
$$\prod_{S} (a - b\alpha) = \gamma^2$$
&lt;hr>
&lt;h2 id="финальный-этап-слияние-миров-и-взлом-криптографии">Финальный этап: Слияние миров и взлом криптографии
&lt;/h2>&lt;p>Наконец, все кусочки головоломки на месте.&lt;/p>
&lt;p>&lt;strong>[Элемент в мире алгебраического поля (Мир A)]&lt;/strong>
$\gamma^2 = \prod (a - b\alpha)$
(Используйте алгоритм извлечения квадратного корня, чтобы найти $\gamma$)&lt;/p>
&lt;p>&lt;strong>[Элемент в реальном мире (мир рациональных чисел)]&lt;/strong>
$V^2 = \prod (a - bm)$
(Это просто обычное умножение целых чисел, поэтому квадратный корень $V$ можно найти легко)&lt;/p>
&lt;p>Теперь настало время для работы первого магического моста, который мы создали, &lt;strong>гомоморфизма $\phi$&lt;/strong>.
Мы переносим элемент $\gamma$ из Мира A в Мир B (мир остатков $N$) с помощью $\phi$ (отображения, которое подставляет $m$ вместо $\alpha$).
&lt;/p>
$$Y = \phi(\gamma) \pmod N$$
&lt;p>С другой стороны, мы берем $V$, созданный в реальном мире, прямо в мир остатков и называем его $X$.
&lt;/p>
$$X = V \pmod N$$
&lt;p>Благодаря свойству гомоморфизма &amp;ldquo;сохранять структуру&amp;rdquo;, квадратичное отношение, которое было истинным в Мире A, идеально сохраняется в Мире B (мире по модулю $N$).
Более того, поскольку исходные пары $(a, b)$ были сформированы так, чтобы соответствовать как $a - b\alpha$ и $a - bm$, эти $X$ и $Y$ сталкиваются в мире по модулю $N$ и порождают следующее абсолютное уравнение:&lt;/p>
&lt;p>&lt;strong>$$X^2 \equiv Y^2 \pmod N$$&lt;/strong>&lt;/p>
&lt;p>Теперь остается только молиться, чтобы $X$ и $Y$ не были тривиальными решениями ($X \equiv \pm Y$), а затем мы вычисляем:
&lt;strong>$\gcd(X - Y, N)$&lt;/strong>&lt;/p>
&lt;p>Если это нетривиальное решение, алгоритм Евклида пронесется за 0,001 секунды, и секретные простые числа $p$ и $q$, которые являются сердцем криптографии RSA, будут выведены на экран.&lt;/p>
&lt;hr>
&lt;p>Это и есть полная картина &lt;strong>&amp;ldquo;Общего метода решета числового поля (GNFS)&amp;rdquo;&lt;/strong>, который объединяет в себе суть современной математики.&lt;/p></description></item><item><title>Что такое Общий метод решета числового поля (GNFS) — сильнейшая математика человечества, взламывающая криптографию интернета?</title><link>http://kenji.blog/ru/p/%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%8D%E3%83%83%E3%83%88%E3%81%AE%E6%9A%97%E5%8F%B7%E3%82%92%E7%A0%B4%E3%82%8B%E4%BA%BA%E9%A1%9E%E6%9C%80%E5%BC%B7%E3%81%AE%E6%95%B0%E5%AD%A6%E4%B8%80%E8%88%AC%E6%95%B0%E4%BD%93%E7%AF%A9%E6%B3%95gnfs%E3%81%A8%E3%81%AF/</link><pubDate>Sat, 05 Sep 2026 02:09:08 +0900</pubDate><guid>http://kenji.blog/ru/p/%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%8D%E3%83%83%E3%83%88%E3%81%AE%E6%9A%97%E5%8F%B7%E3%82%92%E7%A0%B4%E3%82%8B%E4%BA%BA%E9%A1%9E%E6%9C%80%E5%BC%B7%E3%81%AE%E6%95%B0%E5%AD%A6%E4%B8%80%E8%88%AC%E6%95%B0%E4%BD%93%E7%AF%A9%E6%B3%95gnfs%E3%81%A8%E3%81%AF/</guid><description>&lt;img src="http://kenji.blog/p/%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%8D%E3%83%83%E3%83%88%E3%81%AE%E6%9A%97%E5%8F%B7%E3%82%92%E7%A0%B4%E3%82%8B%E4%BA%BA%E9%A1%9E%E6%9C%80%E5%BC%B7%E3%81%AE%E6%95%B0%E5%AD%A6%E4%B8%80%E8%88%AC%E6%95%B0%E4%BD%93%E7%AF%A9%E6%B3%95gnfs%E3%81%A8%E3%81%AF/gnfs_two_worlds_1788542142485.jpg" alt="Featured image of post Что такое Общий метод решета числового поля (GNFS) — сильнейшая математика человечества, взламывающая криптографию интернета?" />&lt;h1 id="что-такое-общий-метод-решета-числового-поля-gnfs--сильнейшая-математика-человечества-взламывающая-криптографию-интернета">Что такое Общий метод решета числового поля (GNFS) — сильнейшая математика человечества, взламывающая криптографию интернета?
&lt;/h1>&lt;p>Интернет, которым мы пользуемся каждый день. Все наши коммуникации, будь то сообщения в LINE, видео на YouTube или покупки на Amazon, защищены «криптографией».
В настоящее время самым распространенным алгоритмом шифрования в мире является «шифр RSA».&lt;/p>
&lt;p>Суть защиты RSA очень проста. Она использует математическое свойство, заключающееся в том, что &lt;strong>«даже компьютеры не могут решить задачу факторизации гигантских чисел на простые множители»&lt;/strong> .
Например, для числа «15» сразу понятно, что это «3 × 5». Но как только число становится «270-значным», даже если объединить все суперкомпьютеры мира, на его решение уйдут сотни миллионов лет.&lt;/p>
&lt;p>Однако математики тоже не сидят сложа руки. Чтобы взломать этот неприступный шифр, человечество создало магический алгоритм (вычислительную процедуру) под названием &lt;strong>«Общий метод решета числового поля (GNFS — General Number Field Sieve)»&lt;/strong> .&lt;/p>
&lt;p>В этой статье мы не будем использовать сложные технические термины, а опираясь только на знания &lt;strong>математики средней школы (разложение на простые множители, алгебраические выражения, наибольший общий делитель)&lt;/strong> , полностью шаг за шагом объясним, как этот «сильнейший алгоритм человечества» взламывает шифры!&lt;/p>
&lt;hr>
&lt;h2 id="глава-1-цель-взлома--формула-из-средней-школы">Глава 1: Цель взлома — «формула из средней школы»
&lt;/h2>&lt;p>Главный прием против факторизации гигантских чисел. Это формула, которую изучают в средних классах.&lt;/p>
&lt;blockquote>
&lt;p>&lt;strong>$X^2 - Y^2 = (X + Y)(X - Y)$&lt;/strong>&lt;/p>
&lt;/blockquote>
&lt;p>Вы можете подумать: «Э-э, неужели такая базовая формула может взломать шифр?». Однако это и есть тот самый главный ключ, который все открывает.&lt;/p>
&lt;p>Главная цель при взломе шифра — найти для огромного числа $N$ &lt;strong>«такие числа ($X$ и $Y$), что остатки от деления $X^2$ и $Y^2$ на $N$ будут одинаковыми»&lt;/strong> .&lt;/p>
&lt;h3 id="почему-одинаковые-остатки-могут-взломать-шифр">Почему «одинаковые остатки» могут взломать шифр?
&lt;/h3>&lt;p>Предположим, у двух чисел $X^2$ и $Y^2$ «остатки от деления на $N$ одинаковые».
Одинаковые остатки означают, что при вычитании &lt;strong>«$X^2 - Y^2$» результат обязательно будет без остатка делиться на $N$ (станет кратным $N$)&lt;/strong> .&lt;/p>
&lt;p>Здесь давайте представим, что огромное число $N$, используемое в шифре, образовано умножением двух секретных простых чисел ($p$ и $q$) ($N = p \times q$).&lt;/p>
&lt;p>Если разложить на множители $X^2 - Y^2$, то получится &lt;strong>$(X - Y)(X + Y)$&lt;/strong> .
То, что это число кратно $N$, означает, что где-то в этом умножении спрятаны секретные простые числа $p$ и $q$.&lt;/p>
&lt;p>И тут происходит чудо.
Математическая вероятность того, что два простых числа $p$ и $q$ разойдутся по разным «комнатам» — &lt;strong>«$p$ в комнату $(X - Y)$», а «$q$ в комнату $(X + Y)$»&lt;/strong> — составляет ровно &lt;strong>50% (одна вторая)&lt;/strong> .&lt;/p>
&lt;p>Предположим, что только простое число $p$ попало в комнату $(X - Y)$. Давайте вычислим &lt;strong>«наибольший общий делитель (самый большой общий компонент)»&lt;/strong> между $(X - Y)$ и $N$.&lt;/p>
&lt;ul>
&lt;li>Содержимое $(X - Y)$ = $p \times$ какое-то число&lt;/li>
&lt;li>Содержимое $N$ = $p \times q$
Единственный общий компонент здесь — это &lt;strong>«$p$»&lt;/strong> !&lt;/li>
&lt;/ul>
&lt;p>Другими словами, в момент вычисления наибольшего общего делителя скрытое простое число $p$ внезапно выпадает, и шифр оказывается полностью взломанным. (&lt;em>Наибольший общий делитель можно моментально вычислить даже на смартфоне с помощью «Алгоритма Евклида»&lt;/em>)&lt;/p>
&lt;p>&lt;strong>[Мини-колонка: Почему именно квадрат? Разве куб или удвоение не подойдут?]&lt;/strong>&lt;/p>
&lt;blockquote>
&lt;p>Если взять «$2X - 2Y$», это превратится в $2(X - Y)$, и останется только одна комната, так что простые числа разделить не получится. Если взять «$X^3 - Y^3$», размеры комнат станут несбалансированными, и вычисления станут неоправданно тяжелыми. Для идеального разделения двух простых чисел «квадрат», образующий две красивые комнаты, является самым оптимальным вариантом.&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;h2 id="глава-2-как-найти-x-и-y-головоломка-по-сбору-карточек-с-простыми-числами">Глава 2: Как найти X и Y? «Головоломка по сбору карточек с простыми числами»
&lt;/h2>&lt;p>Цель ясна. Однако, если пытаться искать «$X^2$ и $Y^2$ с одинаковыми остатками» наугад, мы не найдем их до самого конца существования Вселенной.
Поэтому математики придумали гениальный метод под названием &lt;strong>«Головоломка по сбору карточек с простыми числами»&lt;/strong> .&lt;/p>
&lt;h3 id="шаг-1-просеивание-только-золотого-песка-гладких-чисел">Шаг 1: Просеивание только золотого песка (гладких чисел)
&lt;/h3>&lt;p>Сначала мы берем произвольное число $Z$, возводим его в квадрат и вычисляем остаток $W$ от деления на $N$.
(Мир остатков: $Z^2 = W$)&lt;/p>
&lt;p>Полученный остаток $W$ мы раскладываем на простые множители. Здесь, только когда получается &lt;strong>«$W$, состоящее исключительно из маленьких простых чисел, таких как 2, 3, 5, 7»&lt;/strong> , мы оставляем эту формулу как «выигрышную карточку». Если примешивается большое простое число — мы ее выбрасываем.
Это похоже на работу с ситом (решетом) в реке: мы отбрасываем большие камни и собираем только золотой песок.&lt;/p>
&lt;h3 id="шаг-2-головоломка-с-приведением-к-четному-числу">Шаг 2: Головоломка с приведением к «четному числу»
&lt;/h3>&lt;p>Предположим, мы собрали 3 таких карточки с золотым песком:&lt;/p>
&lt;ul>
&lt;li>Карточка A: $Z_1^2 = 2^3 \times 3^1$&lt;/li>
&lt;li>Карточка B: $Z_2^2 = 2^1 \times 5^1$&lt;/li>
&lt;li>Карточка C: $Z_3^2 = 3^1 \times 5^1$&lt;/li>
&lt;/ul>
&lt;p>Давайте перемножим их все.
Правая сторона станет $(2^3 \times 3^1) \times (2^1 \times 5^1) \times (3^1 \times 5^1)$,
а после упрощения получится &lt;strong>«$2^4 \times 3^2 \times 5^2$»&lt;/strong> .&lt;/p>
&lt;p>Поразительно, но количество простых чисел стало «4, 2, 2» — &lt;strong>все они стали четными&lt;/strong> !
То, что все они стали четными, означает, что если поделить их количество пополам, мы получим «квадрат чего-либо».
А именно: $(2^2 \times 3^1 \times 5^1)^2 = (60)^2$.&lt;/p>
&lt;p>Поскольку левая сторона равна $(Z_1 \times Z_2 \times Z_3)^2$, мы, наконец, получаем:
&lt;strong>$X = (Z_1 \times Z_2 \times Z_3)$&lt;/strong>
&lt;strong>$Y = 60$&lt;/strong>
Долгожданная пара «$X^2 = Y^2$» завершена!&lt;/p>
&lt;p>Для компьютеров головоломки с подсчетом того, «четное число или нечетное (0 или 1)», даются очень легко, поэтому с помощью этого метода можно очень быстро найти $X$ и $Y$.&lt;/p>
&lt;hr>
&lt;h2 id="глава-3-стена-отчаяния-на-пути">Глава 3: Стена отчаяния на пути
&lt;/h2>&lt;p>Казалось бы, теперь любой шифр можно взломать! &amp;hellip;Но тут возникает огромная проблема.
Если число шифра $N$ имеет длину до «100 цифр», этот метод (называемый методом квадратичного решета) справляется. Но когда $N$ становится «200-значным или 300-значным», промежуточное значение $W$ становится слишком гигантским.&lt;/p>
&lt;p>Когда числа становятся слишком огромными, «числа, состоящие только из маленьких простых чисел (золотой песок)», перестают появляться вообще. Найти их становится сложнее, чем контактную линзу в пустыне, и собрать карточки для решения головоломки становится абсолютно невозможно.&lt;/p>
&lt;p>И вот здесь наконец появляется совершенное оружие человечества — &lt;strong>«Общий метод решета числового поля (GNFS)»&lt;/strong> .&lt;/p>
&lt;hr>
&lt;h2 id="глава-4-гениальная-идея-человечества--создание-двух-миров">Глава 4: Гениальная идея человечества — создание «двух миров»
&lt;/h2>&lt;p>Гениальность идеи GNFS заключается в следующем: &lt;strong>«Раз числа становятся огромными потому, что мы считаем только в реальном мире, давайте создадим &amp;ldquo;параллельный мир&amp;rdquo; с помощью полиномов (алгебраических выражений) и разделим вычислительную нагрузку на две части»&lt;/strong> .&lt;/p>
&lt;h3 id="магия-алгебраических-выражений">Магия алгебраических выражений
&lt;/h3>&lt;p>GNFS преобразует огромное число $N$ в алгебраическое выражение, используя базовое число $m$.
Например, если $N=100$, мы выбираем $m=4$, тогда $100 = 4^3 + 2(4^2) + 4$.
Используя переменную $x$, мы превращаем это в выражение (параллельный мир): &lt;strong>$f(x) = x^3 + 2x^2 + x$&lt;/strong> .&lt;/p>
&lt;p>Самое интересное в этом выражении — его свойство: &lt;strong>«Если подставить вместо $x$ число $m$ (в данном примере 4), то можно в любой момент &amp;ldquo;телепортироваться&amp;rdquo; обратно к реальному числу $N$»&lt;/strong> .&lt;/p>
&lt;h3 id="поиск-золотого-песка-одновременно-в-двух-мирах">Поиск золотого песка одновременно в двух мирах
&lt;/h3>&lt;p>GNFS генерирует множество произвольных пар целых чисел $(a, b)$ и одновременно выполняет два вычисления:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Реальный мир&lt;/strong>: $a - b \times m$&lt;/li>
&lt;li>&lt;strong>Алгебраический мир&lt;/strong>: значение $a - b \times x$, вычисленное по правилам алгебраических выражений&lt;/li>
&lt;/ol>
&lt;p>Благодаря разделению задачи на два мира, размер используемых чисел радикально уменьшается (становится «легче»). Представьте себе, что гигантский валун разбили на два удобных камня.&lt;/p>
&lt;p>Затем с помощью сита (решета) отсеиваются и собираются только те чудесные пары $(a, b)$, в которых &lt;strong>«и в реальном мире, и в алгебраическом мире результаты состоят только из маленьких простых чисел (являются золотым песком)»&lt;/strong> . Отсюда и происходит название «метод решета числового поля».&lt;/p>
&lt;h3 id="момент-взлома-шифра">Момент взлома шифра
&lt;/h3>&lt;p>Когда из обоих миров собираются десятки миллионов «карточек с золотым песком», с помощью матричных вычислений на суперкомпьютерах находится «комбинация, при которой количество простых чисел становится полностью четным», точно так же, как во 2-й главе.&lt;/p>
&lt;p>Когда комбинация найдена:&lt;/p>
&lt;ul>
&lt;li>Число в квадрате, полученное в реальном мире, обозначается как &lt;strong>$X^2$&lt;/strong>&lt;/li>
&lt;li>Выражение в квадрате, полученное в алгебраическом мире, обозначается как &lt;strong>$Y(x)^2$&lt;/strong>&lt;/li>
&lt;/ul>
&lt;p>И наконец, мы подставляем $m$ вместо $x$ в $Y(x)$ алгебраического мира, телепортируя его и объединяя с реальным миром.
И тут, как по математическому волшебству, строго выполняется условие &lt;strong>«остатки $X^2$ и $Y^2$ одинаковы»&lt;/strong> !&lt;/p>
&lt;p>Дальше, как было описано в 1-й главе, достаточно вычислить наибольший общий делитель $X - Y$ и $N$, и неприступный шифр RSA с грохотом рассыпается, открывая секретные простые числа.&lt;/p>
&lt;hr>
&lt;h2 id="заключение-математика-не-заканчивается">Заключение: Математика не заканчивается
&lt;/h2>&lt;p>Возможно, вы подумали: «Отлично, с помощью GNFS можно взломать любой шифр!».
Однако шифр RSA не сдается. В современном интернете используется чудовищно огромное число под названием «RSA-2048 (около 617 цифр)».&lt;/p>
&lt;p>Каким бы сильным алгоритмом ни был GNFS, считается, что даже для взлома 270-значного числа (RSA-270) потребовались бы тысячи, а то и десятки тысяч лет, даже если бы объединили все компьютеры мира. На данный момент наши данные в LINE и банках в безопасности.&lt;/p>
&lt;p>Но что, если появится &lt;strong>«магия, способная мгновенно находить $X$ и $Y$ для любого сколь угодно гигантского числа»&lt;/strong> ?
На самом деле, самое близкое к этому — разрабатываемые сейчас &lt;strong>«квантовые компьютеры (Алгоритм Шора)»&lt;/strong> . Математически доказано, что, используя волновую природу квантовой механики, можно проигнорировать утомительную головоломку со сбором карточек и вытянуть правильный ответ за один раз.&lt;/p>
&lt;p>Бесконечная битва умов между создателями шифров (защитой) и создателями алгоритмов взлома (атакой).
Когда узнаешь, что «разложение на простые множители» и «алгебраические выражения», которые изучают в средней школе, на самом деле являются оружием, ожесточенно сражающимся на переднем крае глобальной безопасности, разве уроки математики не начинают казаться чуточку интереснее?&lt;/p>
&lt;p>Возможно, именно вы, читающий эту статью, в будущем откроете новый сильнейший алгоритм!&lt;/p>
&lt;hr>
&lt;p>&lt;em>(※Эта статья концептуализирует математическую привлекательность взлома шифров для школьников. Настоящий GNFS рассчитывается строго с использованием высшей университетской математики, такой как идеальные группы классов алгебраических числовых полей и гомоморфизмы)&lt;/em>&lt;/p></description></item></channel></rss>