EssayAI
Блог
Блог

Как быстро возвести в степень: бинарный алгоритм

Запрос

Дано: основание a=7a = 7, показатель n=93n = 93, модуль m=101m = 101. Найти: остаток 793 mod 1017^{93} \bmod 101 и число умножений, которое на это уйдёт.

Считать сам 7937^{93} не нужно: показатель раскладывается в двоичную запись 93=1011101293 = 1011101_2, основание последовательно возводится в квадрат по модулю, и потом перемножаются только нужные квадраты. Ответ: 793≡55(mod101)7^{93} \equiv 55 \pmod{101}, и получен он за 10 умножений вместо 92. Калькулятор сверху проходит ту же лестницу для любых aa, nn и mm, а ниже разбор по шагам.

Решение по шагам

Дано. a=7a = 7, n=93n = 93, m=101m = 101. Найти: 793 mod 1017^{93} \bmod 101.

Шаг 1. Раскладываем показатель в двоичную запись. Делим 93 на 2 с остатком, пока не дойдём до нуля, и читаем остатки снизу вверх:

93=64+16+8+4+1=10111012.93 = 64 + 16 + 8 + 4 + 1 = 1011101_2.

Единицы стоят на местах 202^0, 222^2, 232^3, 242^4 и 262^6, поэтому исходная степень распадается в произведение пяти множителей:

793=764⋅716⋅78⋅74⋅71.7^{93} = 7^{64} \cdot 7^{16} \cdot 7^{8} \cdot 7^{4} \cdot 7^{1}.

Шаг 2. Строим таблицу последовательных квадратов. Каждая строка получается возведением предыдущей в квадрат, и остаток берётся сразу же, поэтому числа никогда не выходят за пределы 1012101^2:

kkЧто считаемРезультатОстаток по модулю 101
07777
1727^24949
249249^2240178
378278^2608424
424224^257671
571271^2504192
692292^2846481

Шести умножений хватило, чтобы получить 764≡81(mod101)7^{64} \equiv 81 \pmod{101}, хотя в самом числе 7647^{64} больше полусотни цифр.

Шаг 3. Перемножаем отмеченные строки. Нужны k=0,2,3,4,6k = 0, 2, 3, 4, 6, то есть остатки 7, 78, 24, 71 и 81. Умножаем по очереди и после каждого умножения сразу приводим по модулю:

7⋅78=546=5⋅101+41≡41,41⋅24=984=9⋅101+75≡75,75⋅71=5325=52⋅101+73≡73,73⋅81=5913=58⋅101+55≡55.\begin{aligned} 7 \cdot 78 &= 546 = 5 \cdot 101 + 41 &&\equiv 41, \\ 41 \cdot 24 &= 984 = 9 \cdot 101 + 75 &&\equiv 75, \\ 75 \cdot 71 &= 5325 = 52 \cdot 101 + 73 &&\equiv 73, \\ 73 \cdot 81 &= 5913 = 58 \cdot 101 + 55 &&\equiv 55. \end{aligned}

Шаг 4. Считаем цену вычисления. Шесть возведений в квадрат в таблице плюс четыре умножения при сборке дают десять операций. Наивное перемножение семёрки на себя потребовало бы 92 умножения, то есть в 9,2 раза больше, а для показателя в тысячу разрыв стал бы стократным.

Ответ: 793≡55(mod101)7^{93} \equiv 55 \pmod{101}, вычислено за 10 умножений вместо 92.

Формула: почему показатель можно удваивать

Весь алгоритм держится на двух тождествах, которые разбирают показатель по чётности:

a2k=(ak)2,a2k+1=(ak)2⋅a.a^{2k} = \left(a^{k}\right)^{2}, \qquad a^{2k+1} = \left(a^{k}\right)^{2} \cdot a.

Чётный показатель стоит ровно одного возведения в квадрат, нечётный обходится в квадрат плюс одно домножение на основание. За один шаг показатель уменьшается вдвое, поэтому шагов будет столько, сколько цифр в двоичной записи nn, а не столько, сколько единиц в самом nn.

Второе, что делает счёт возможным, - свойство сравнений: остаток произведения зависит только от остатков сомножителей,

(x⋅y) mod m=((x mod m)⋅(y mod m)) mod m.(x \cdot y) \bmod m = \left((x \bmod m) \cdot (y \bmod m)\right) \bmod m.

Отсюда правило, которое экономит не время, а разрядность: приводить по модулю нужно после каждого умножения, а не в конце. Тогда любое промежуточное произведение меньше m2m^2 и помещается в обычный целый тип, тогда как честный 7937^{93} занимает 79 десятичных цифр.

Общее число умножений считается по двоичной записи точно:

N(n)=⌊log⁡2n⌋+s(n)−1,N(n) = \lfloor \log_2 n \rfloor + s(n) - 1,

где s(n)s(n) - количество единиц. Для n=93n = 93 получаем 6+5−1=106 + 5 - 1 = 10, что и вышло в разборе. В худшем случае, когда все биты единичные, оценка равна 2⌊log⁡2n⌋2\lfloor \log_2 n \rfloor, в лучшем (степень двойки) - просто ⌊log⁡2n⌋\lfloor \log_2 n \rfloor. Обе оценки логарифмические: показателю в миллион нужно около тридцати умножений.

Второй способ: лестница слева направо

Таблицу квадратов можно не хранить. Заведём один остаток r=1r = 1 и пройдём двоичную запись показателя от старшего бита к младшему: на каждом бите возводим rr в квадрат, а если бит равен единице, дополнительно умножаем на основание. Показатель при этом собирается по схеме Горнера: удваивается и иногда получает плюс единицу.

Бит показателя1011101
Накопленный показатель12511234693
Остаток по модулю 1017494151272255

Последний столбец совпал с ответом первого способа, и число умножений то же самое: шесть квадрирований и четыре домножения. Разница только в памяти: способ справа налево держит таблицу из ⌊log⁡2n⌋+1\lfloor \log_2 n \rfloor + 1 значений, способ слева направо - одно число. Именно поэтому в библиотеках длинной арифметики реализован обычно второй вариант, а на бумаге удобнее первый: таблица квадратов наглядна и её легко проверить.

График в калькуляторе сверху показывает как раз эту лестницу: столбик - остаток после очередного бита, линия - сколько умножений уже сделано. Переключатель разворачивает второй вид, где видно расхождение наивного и бинарного счёта при росте показателя.

Проверка ответа малой теоремой Ферма

Модуль 101 простой, а основание 7 на него не делится, поэтому работает малая теорема Ферма: 7100≡1(mod101)7^{100} \equiv 1 \pmod{101}. Показателю 93 не хватает до сотни ровно семёрки, значит 793⋅77≡1(mod101)7^{93} \cdot 7^{7} \equiv 1 \pmod{101}, и найденный остаток обязан быть обратным к 777^7.

Считаем правую часть отдельно: 77=74⋅72⋅7≡78⋅49⋅7≡90(mod101)7^{7} = 7^{4} \cdot 7^{2} \cdot 7 \equiv 78 \cdot 49 \cdot 7 \equiv 90 \pmod{101}. Проверяем произведение: 55⋅90=4950=49⋅101+1≡155 \cdot 90 = 4950 = 49 \cdot 101 + 1 \equiv 1. Сошлось, ответ верен.

Та же теорема даёт полезный приём для огромных показателей: если gcd⁡(a,m)=1\gcd(a, m) = 1, показатель заранее сокращается по модулю φ(m)\varphi(m), а для простого mm - по модулю m−1m - 1. Например, 72026 mod 1017^{2026} \bmod 101 сводится к 726 mod 1017^{26} \bmod 101, потому что 2026=20⋅100+262026 = 20 \cdot 100 + 26, и бинарный алгоритм после такого сокращения работает с показателем из пяти бит вместо одиннадцати. Проверять взаимную простоту обязательно: при gcd⁡(a,m)≠1\gcd(a, m) \neq 1 сокращение показателя неверно.

Где это считают: большие модули и степени матриц

Возведение в степень по модулю - рабочая операция асимметричной криптографии, и без бинарного алгоритма она была бы невыполнима: показатель там имеет порядок 220482^{2048}, а бинарный способ укладывается примерно в три тысячи умножений. На этой операции построены обмен ключами Диффи-Хеллмана и схема Эль-Гамаля; модульная арифметика в том же виде, только над матрицами, лежит в основе шифра Хилла.

Алгоритм не привязан к числам: он работает в любой структуре с ассоциативным умножением. Для матриц это даёт быстрое вычисление PnP^n - например, при поиске распределения цепи Маркова через матрицу переходов или при вычислении nn-го числа Фибоначчи за логарифмическое время через степень матрицы 2×22 \times 2.

Частые ошибки

  • Сначала считают степень, потом берут остаток. Число 7937^{93} имеет 79 цифр, а при криптографических размерах не поместится в память вообще. Приводить по модулю нужно после каждого умножения.
  • Пропускают приведение внутри таблицы квадратов. Если возводить в квадрат уже приведённый остаток, произведение не превысит m2m^2; если тянуть полное число, разрядность удваивается на каждой строке.
  • Теряют или добавляют бит. Число сомножителей в сборке равно числу единиц: для 93 их пять. Быстрая проверка - сумма выбранных степеней двойки должна дать сам показатель: 64+16+8+4+1=9364 + 16 + 8 + 4 + 1 = 93.
  • Перемножают показатели вместо сложения. При сборке 764⋅716=7807^{64} \cdot 7^{16} = 7^{80}, а не 710247^{1024}: показатели складываются, это и есть смысл двоичного разложения.
  • Сокращают показатель по модулю mm, а не по φ(m)\varphi(m). Правильно 72026≡726(mod101)7^{2026} \equiv 7^{26} \pmod{101}, потому что φ(101)=100\varphi(101) = 100; сокращение по 101 даёт другое, неверное число.
  • Читают двоичную запись не с того конца. В способе справа налево младший бит соответствует a1a^1, в способе слева направо разбор начинается со старшего бита. Смешение порядков даёт правдоподобный, но неверный остаток.

FAQ

Сколько умножений нужно для показателя из 2048 бит? Квадрирований будет 2047, домножений в среднем около половины от числа бит, то есть примерно 1024. Итого порядка трёх тысяч умножений вместо астрономических 220482^{2048}. Именно эта разница делает работоспособной криптографию с открытым ключом.

Чем быстрое возведение отличается от бинарного и дихотомического? Ничем: это три названия одного алгоритма. Встречаются также термины «возведение в степень методом квадрирования» и английское square and multiply.

Можно ли обойтись без таблицы квадратов? Да, для этого и нужен проход слева направо: он хранит единственный остаток и делает то же число умножений. Таблица удобна на бумаге, когда решение нужно показать целиком.

Что делать, если модуль составной? Сам алгоритм не меняется, он не требует простоты модуля. Отличается только предварительное сокращение показателя: вместо m−1m - 1 берётся φ(m)\varphi(m), а для модуля вида m=pqm = pq расчёт часто разбивают по китайской теореме об остатках и считают две степени по меньшим модулям.

Коротко

  1. Разложить показатель в двоичную запись: 93=1011101293 = 1011101_2, единицы стоят на местах 20,22,23,24,262^0, 2^2, 2^3, 2^4, 2^6.
  2. Построить таблицу квадратов по модулю: 7, 49, 78, 24, 71, 92, 81 - каждая строка есть квадрат предыдущей, приведённый по модулю 101.
  3. Перемножить строки с единичными битами, приводя по модулю после каждого умножения: 7→41→75→73→557 \to 41 \to 75 \to 73 \to 55.
  4. Ответ: 793≡55(mod101)7^{93} \equiv 55 \pmod{101} за 10 умножений против 92 при перемножении в лоб; общая оценка равна ⌊log⁡2n⌋+s(n)−1\lfloor \log_2 n \rfloor + s(n) - 1.
  5. Проверить результат малой теоремой Ферма: 55⋅77≡55⋅90≡1(mod101)55 \cdot 7^{7} \equiv 55 \cdot 90 \equiv 1 \pmod{101}.
Задача в тетради или методичке? Сфотографируйте условие - сервис распознает его и решит по шагам с пояснениями.

Похожие задачи

Теория чисел/криптография

Как найти обратное по модулю: расширенный алгоритм Евклида

Как найти обратное по модулю: разбор на числах 37 и 120, условие существования через НОД, таблица расширенного алгоритма Евклида, приведение коэффициента и проверка остатка.

Теория чисел/криптография

Как найти функцию Эйлера: разбор на числе 7560

Как найти функцию Эйлера: разбор числа 7560 по шагам, каноническое разложение, формула через произведение скобок по простым делителям, проверка мультипликативностью и теорема Эйлера.

Теория чисел/криптография

Как найти первообразный корень: критерий и пример

Как найти первообразный корень по модулю: функция Эйлера, критерий через её простые делители, проверка кандидатов 2, 3, 5 и 6 по модулю 41 и таблица индексов.

Теория чисел/криптография

Как решить систему сравнений: китайская теорема об остатках

Как решить систему сравнений x = 2 (mod 3), x = 3 (mod 5), x = 2 (mod 7): проверка взаимной простоты модулей, сборка ответа по китайской теореме об остатках и проверка подстановкой.

Теория чисел/криптография

Как решить сравнение по модулю: 42x = 30 (mod 78)

Как решить сравнение по модулю на примере 42x = 30 (mod 78): критерий разрешимости через НОД, число решений, сокращение сравнения вместе с модулем и все шесть классов вычетов.

Теория чисел/криптография

Как найти НОК двух чисел: два способа с примером

Как найти НОК двух чисел на примере 126 и 120: разложение на простые множители со старшими степенями, формула через НОД, проверка ответа и задача про шестерни с зубьями.