Как найти обратный элемент в кольце вычетов

Есть два пути для решения этой задачи.

Путь первый — использование расширенного алгоритма Евклида.

Алгоритм Евклида ищет НОД двух чисел. Расширенный алгоритм Евклида одновременно с этим представляет НОД как целочисленную линейную комбинацию исходных чисел:

Ka∙a + Kb∙b = (a, b)

Как легко заметить, если A и C не являются взаимно простыми, то решения нет, а если являются — то коэффициент при A и будет искомым обратным элементом (для доказательства можно заменить в формуле выше b на C и взять обе части равенства по модулю C).

Рекурсивный алгоритм довольно прост. На очередном шаге большее из двух чисел (для определенности, a) представляется как c + k∙b, после чего алгоритм вызывается рекурсивно для (b, c):

Ka∙(c + k∙b) + Kb∙b = (a, b)
Ka∙c + (Kb + Ka∙k)∙b = (c + k∙b, b) = (c, b)
Kc1∙c + Kb1∙b = (c, b)

Отсюда имеем Ka = Kc1 и Kb = Kb1 — Kc1∙k

Получаем примерно такой алгоритм:

ФУНКЦИЯ НОД(a, b) -> (d, Ka, Kb):
    ЕСЛИ (b == 0) ВЕРНУТЬ (a, 1, 0)

    (d, Kb1, Kc1) = НОД(b, a % b);
    ВЕРНУТЬ (d, Kc1, Kb1 - ⌊a/b⌋ ∙ Kc1);

Итеративный алгоритм столь же прост в реализации, но сложнее в понимании. Проще всего использовать матрицы. Для начала, следует записать преобразование коэффициентов в матричном виде:

                     | 0    1  |
(Ka Kb) = (Kb1, Kc1) |         |
                     | 1 -⌊a/b⌋ |

Эти матричные множители можно будет накопить:

|K11 K12|   | 0     1  | |K11` K12`| 
|       | = |          | |         | 
|K21 K22|   | 1  -⌊a/b⌋ | |K21` K22`| 

Получается следующий алгоритм:

ФУНКЦИЯ НОД(a, b) -> (d, Ka, Kb):
    K = (1, 0)(0, 1) // Начинаем с единичной матрицы

    ПОКА b > 0
       K = (K[1, 0], K[1, 1])(K[0, 0] - ⌊a/b⌋∙K[1, 0], K[0, 1] - ⌊a/b⌋∙K[1, 1])
       (a, b) = (b, a % b)

    ВЕРНУТЬ (a, (K[0, 0], K[0, 1])

Теперь, когда у нас есть НОД, осталось найти НОД(A, C), проверить что он равен 1 и взять (Ka % C) в качестве искомого обратного числа.

Время работы — порядка log A по основанию φ итераций (это связано с тем, что худший случай для алгоритма Евклида — соседние числа Фибоначчи).

Путь второй — использование формулы Эйлера

Если число C заранее известно, или есть достаточно времени на подготовку, то можно воспользоваться формулой Эйлера:

A ^ φ(C) = 1 (mod C) для взаимно простых A и C

Поскольку для имеющих нетривиальные общие делители A и C задача решения все равно не имеет — ограничение нам не помешает.

В соответствии с формулой, ответом будет A ^ (φ(C) - 1) % C. Быстро найти его можно при помощи алгоритма быстрого возведения в степень:

ФУНКЦИЯ СТЕПЕНЬ (a, x, c):
     b = 1

     ПОКА x > 0:
       ЕСЛИ x - НЕЧЕТНОЕ, ТО 
         x = x - 1
         b = (b * a) % c
       ИНАЧЕ
         x = x / 2
         a = (a * a) % c

     ВЕРНУТЬ b

Корректность этого алгоритма легко доказывается если заметить что a ^ x * b — его инвариант.

Разумеется, после получения ответа надо будет проверить что он правильный, если он будет неверным — значит, ответа вовсе не существует (A и C имеют общие делители).

Этот алгоритм будет работать быстрее чем алгоритм Евклида, потому что тут основание логарифма больше, а сами итерации — проще. Но для применения этого алгоритма требуется заранее знать φ(C)

Обратный по модулю

❓Инструкция

📘  Калькулятор онлайн для вычисления обратного элемента по модулю в кольце. Алгоритм поддерживает работу с большими числами с некоторыми ограничениями. 

ℹ Использование:

✔ Заполняются два поля — число a и модуль m. Число a — число к которому ищем обратный, m — модуль, по которому ищем.

✔ Калькулятор выдает обратный элемент после нажатия на кнопку «Вычислить».

✔ Если установлена галочка «подробнее», то калькулятор помимо обратного элемента по модулю выдает некоторые этапы вычисления. 

‼ Ограничения:

!Калькулятор поддерживает работу с большими целыми числами (в том числе отрицательными числами для числа a, и только положительными для модулю m) длиной не более 10 000 символов.

📖 Теория

📌 Что значит по модулю?

Синонимом к данному выражению является выражение «остаток от деления«. То есть выражение «5 по модулю 3» эквивалентно выражению «остаток от деления 5 на 3». И в том и в другом случае подразумевается в ответе число 2, так как остаток от деления 5 на 3  = 2.

Стоить отметить тот факт, что по модулю m мы имеем числа от 0 до m — 1. Действительно, остаток от деления на m никогда не превысит m — 1. 

📌 Что такое обратное?

Напомним, что число, умноженное на его обратное, равно 1. Из базовой арифметики мы знаем, что:

✔ Число, обратное к числу A, равно 1 / A, поскольку A * (1 / A) = 1 (например, значение, обратное к 5, равно 1/5).
✔ Все действительные числа, кроме 0, имеют обратную
✔ Умножение числа на обратное к A эквивалентно делению на A (например, 10/5 соответствует 10 * 1/5)

📌 Что такое обратное по модулю?

В модульной арифметике у нас нет операции деления. Тем не менее, у нас есть модульные инверсии.

✔ Модульная инверсия a (mod m) есть a-1
✔ (a * a-1) ≡ 1 (mod m) или эквивалентно (a * a-1) mod m = 1
✔ Только числа, взаимно простые с модулем m, имеют модульное обратное.

Говоря проще, обратным элементом к a по модулю m является такое число b, что остаток от деления (a * b) на модуль m равно единице (a * a-1) mod m = 1

📌 Как найти модульный обратный

Наивный метод нахождения модульного обратного a ( по модулю m) является:
Шаг 1. Рассчитать a * b mod m для значений b от 0 до m — 1
Шаг 2. Модульная инверсия a mod m — это значение b, при котором a * b mod m = 1

Обратите внимание, что термин b mod m может иметь только целочисленное значение от 0 до m — 1, поэтому тестирование больших значений чем (m-1) для b является излишним. 

Вы наверно уже догадались, что наивный метод является очень медленным. Перебор всех чисел от 0 до m-1 для большого модуля довольно-таки трудоемкая задача. Существует гораздо более быстрый метод нахождения инверсии a (mod m). Таковым является расширенный алгоритм Евклида, который реализован в данном калькуляторе.

📌 Расширенный алгоритм Евклида

Представим наибольший общий делитель числа a и модуля m в виде ax + my. То есть НОД(a, m) = ax + my. Помним, что обратный элемент существует только тогда, когда a и m взаимно просты, то есть их НОД(a, m) = 1. Отсюда: ax + my = 1 — линейное диофантово уравнение второго порядка. Необходимо решить данное уравнение в целых числах и найти x, y.

Найденный коэффициент x будет являться обратным элементом к a по модулю m. Это следует оттуда, что, если мы возьмём от обеих частей уравнения остаток по модулю m, то получим: ax = 1 (m).

Расширенный алгоритм Евклида, в отличие от классического, помимо наибольшего общего делителя позволяет найти также коэффициенты x, y.

📌 Алгоритм:

Вход: a, m ≠ 0

Выход: d, x, y, такие что d = gcd(a, m) = ax + my

1. [Инициализация] (a0, a1) := (a, m); (x0, x1) := (1, 0); (y0; y1) := (0, 1).

2. [Основной цикл] Пока a1 ≠ 0 выполнять {q = QUO(a0, a1);
(a0, a1) := (a1, a0 — a1q); (x0, x1) := (x1, x0 — x1q); (y0, y1) := (y1, y0 — y1q); 

QUO(a0, a1) — целая часть от деления a0 на a1

3. [Выход] Вернуть (d, x, y) = (a0, x0, y0)

Битовая сложность расширенного алгоритма Евклида равна O((log2(n))2) , где n = max (|a|, |m|)

Непонятен алгоритм? Ничего страшного, примеры ниже именно для этого и предназначены.

➕ Примеры

📍 Пример для наивного метода.

Пусть a = 3, m = 7. То есть нам необходимо найти обратный элемент к 3 по модулю 7.

Шаг 1. Рассчитать a * b mod m для значений B от 0 до m-1. По очереди проверяем числа от 0 до 6.

3 * 0 ≡ 0 (mod 7) — не подходит
3 * 1 ≡ 3 (mod 7)
3 * 2 ≡ 6 (mod 7)
3 * 3 ≡ 9 ≡ 2 (mod 7)
3 * 4 ≡ 12 ≡ 5 (mod 7)
3 * 5 ≡ 15 (mod 7) ≡ 1 (mod 7) <—— Обратное найдено.
3 * 6 ≡ 18 (mod 7) ≡ 4 (mod 7)

при b = 5 выполнилось условие, что a * b ≡ 1 (m). Следовательно, b = 5 является обратным элементом к 3 по модулю 7.

📍 Пример на расширенный алгоритм Евклида.

Пусть аналогично предыдущему примеру имеем a = 3, m = 7. Также, требуется найти обратный элемент к 3 по модулю 7. Согласно алгоритму начинаем заполнять таблицу на каждом этапе цикла.

Итерация q a0 a1 x0 x1 y0 y1
0 3 7 1 0 0 1
1 0 7 3 0 1 1 0
2 2 3 1 1 -2 0 1
3 3 1 0 -2 0 1 -3

После 3-ей итерации получили a1 = 0, строго по алгоритму из раздела «Теория» заканчиваем работу алгоритма.

(d, x, y) = (a0, x0, y0)

(d, x, y) = (1, -2, 1), видим, что d = НОД(3, 7) = 1, следовательно числа 3 и 7 являются взаимно простыми, а значит обратный существует.

📎 Делаем проверку:

3 * (-2) + 7 * 1 = 1
-6 + 7 = 1
1 = 1 — верно!

Обратным элементом к тройке по модулю 7 является x = -2. По модулю 7 число -2 равно 5. Получили, что x = 5 является обратным элементом к 3 по модулю 7.


Калькулятор для вычисления обратного элемента по модулю ниже, теория под ним.

PLANETCALC, Обратный элемент в кольце по модулю

Обратный элемент в кольце по модулю

Обратным к числу a по модулю m называется такое число b, что:
ab equiv 1 pmod m,
Обратный элемент обозначают как a^{-1}.

Для нуля обратного элемента не существует никогда, для остальных же элементов обратный элемент может как существовать, так и нет.
Утверждается, что обратный элемент существует только для тех элементов a, которые взаимно просты с модулем m.

Для нахождения обратного элемента по модулю можно использовать Расширенный алгоритм Евклида.

Для того, чтобы показать это, рассмотрим следующее уравнение:

ax + my = 1

Это линейное диофантово уравнение с двумя переменными, см. Линейные диофантовы уравнения с двумя переменными. Посколько единица может делиться только на единицу, то уравнение имеет решение только если {rm gcd}(a,m)=1.
Решение можно найти с помощью расширенного алгоритма Евклида. При этом, если мы возьмём от обеих частей уравнения остаток по модулю m, то получим:

ax = 1 pmod m

Таким образом, найденное x и будет являться обратным к a.

ЛЕКЦИЯ 3

Метод инварианта цикла.

Здесь мы рассмотрим проектирование цикла на основе инварианта цикла. Данный подход к проектированию оправдан всегда, когда ситуация выглядит достаточно запутанной, и действия, которые должны выполняться в теле цикла не в полне очевидны.

Метод инварианта цикла представляет собой математический подход к проектированию цикла, и его применение приводит к тому, что доказательство правильности выполнения цикла будет иметь силу математического доказательства.

Суть метода, если его разложить по пунктам, состоит в следующем

  • опреределить какие переменные (фазовые переменные) должны изменяться в теле цикла;
  • определить каково долно быть условие завершения цикла (цель цикла), выражающееся через значения фазовых переменных;
  • сформулировать подходящий инвариант цикла (первые три пункта, на самом деле, составляют одно целое);
  • исходя из инварианта цикла и из условия завершения цикла (которое определяет целевые значения входящих в него фазовых переменных) определить, какие именно должны быть преобразования фазовых переменных в теле цикла.

Далее будут рассмотрены примеры использования инварианта цикла.

Задача частичной сортировки массива

На практическом занятии 6 была предложена задача (задача 2, пункт б)) со следующей формулировкой.

Дан некоторый массив A и некоторое значение b. Требуется без использования дополнительных массивов переставить элементы в массивае A так, что бы сначала шли все элементы, меньшие b, затем — все, равные b, и затем — все большие b. Алгоритм должен иметь оценку сложности O(n).

Применим метод инварианта цикла. Для того, чтобы сформулировать инвариант, будет полезно обратиться к рисунку.
fig-1

Как видно из рисунка, весь массив разбивается на 4 последовательные части. Первая часть, с диапазоном индексов 1:k содержит элементы, меньшие b, вторая часть, с диапазоном индеков k+1:l содержит элементы, равные b, последняя (4-я) часть, с диапазоном индексов m+1:n (n-длина массива), содержит элементы большие b. А третья часть, с диапазоном индексов l+1:m содержит элементы, которые пока не разделены по отношению к b.

Задача состоит в том, чтобы составить цикл, в которм величины k, l, m будут меняться (k, l в большую сторону, m — в меньшую). В начальный момент k=l=0, m=n, т.е. первая, вторая и четвертая части массива — пустые, третья часть массива (на рисунке она заштрихована) совпадает со всем массивом A. Цикл должен быть завершен, когда эта 3-я часть станет пустой, т.е. когда станет l==m.

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

n=length(A)
k=l=0
m=n
#=ИНВАРИАНТ: 
A[i] <b for i = 1:k
A[i]==b for i = k+1:l
A[i] >b for i = m+1:n
=#
while l != m
    ...
end

Остается только, глядя на инвариант цикла, и имея в виду цель завершения цикла, записать его тело, в котором ввденные фазовые преременные k, l, m будут изменяться требуемым образом.

А именно, в теле цикла надо будет брать элемент с индексом l+1, и после сравнения его с b, изменить границы частей массива требуемым образом, возможно совершив при этом транспозицию A[l+1] и A[k+1] или A[l+1] и A[m].

В первом случае k и l увеличатся на 1, во втором — m уменьшится на 1, а в третьем случае, когда A[l+1]==b, останется только увеличить на 1 переменную l.

Алгоритм быстрого возведения в целую степень

Пусть дано некоторая величина a и натуральное число n, требуется вычислить $a^n$.

Вот наивный алгоритм вычисления $a^n$, имеющий оценку сложности $O(n)$:

p=1
for i in 1:n
    p *= a
end

Хотелось бы, однако, получить алгоритм с оценкой сложности $O(log(n))$. Надежда на это происходит из того, что в частном случае, когда $n=2^m$, т.е. когда натуральная степень имеет значения 2, 4, 8, 16, 32, … получить алгоритм с логарифмической оценкой сложности очень просто:

# число n - есть некоторая натуральная степень 2 или 1
p=a
while n != 1
    p *= p
    n ÷= 2
end
# p- искомая степень

Или, чтобы для того, чтобы сформулировать соответствующий инвариант цикла, это удобнее будет записать с использованием ещё одной переменной k:

# число n - есть некоторая натуральная степень 2 или 1
p, k = a, n # p=a; k=n
#ИНВАРИАНТ: p^k = a^n
while k != 1
    p *= p
    k ÷= 2 # k гарантированно делится на 2
end

Отметим, что можно было бы еще и так реализовать данный алгоритм:

# число n - есть некоторая натуральная степень 2 или 1
p, k = a, n # p=a; k=1
#ИНВАРИАНТ: p = a^k
while k != n
    p *= p
    k *= 2 
end

Но этот вариант записи алгоритма не удобен для для требуемого обобщения.

И так, в записанном алгоритме, например, при n=8, число итераций будет 3, т.е. $log_28$, при n=16 — $log_2 16= 4$ и т.д.

Однако в общем случае, если число n не есть некоторая степень двойки, это работать не будет. Но, с другой стороны, если даже число n не есть степень двойки, то это число может быть четным (т.е. делиться на 2), а если оно не четное, то после вычитания из него 1 получится четное число, которое тоже можно будет делить пополам.

Таким образом, хотя бы через раз, число n может быть поделено пополам, и не более чем через раз из него придется для этого вычитать 1 (имеется в виду, что после таких действий первоначальное значение n будет заменяться новым значением).

Исходя из этих соображений можно к имеющимся уже фазовым переменным p, k (см. предыдущий вариант) добавить еще одну переменную t с тем, чтобы записать инвариант цикла, охватывающий общий случай:

k, t, p = n, 1, a # k=n; t=1; p=a

#ИНВАРИАНТ: p^k*t=a^n 
while k>0
    ...    
end
#УТВ: t = a^n

Остается только лишь понять как надо изменять фазовые переменные p, k, t, чтобы успешно завершить цикл (и чтобы после кадой итерации выполнялся бы инвариант).

Искомые преобразования фазовых переменных могут быть выведены чисто формально непосредственно из сформулированного инварианта и из того, что на каждой очередной итерации переменная k должна уменьшаться вдое (если ее значение четное), или уменьшаться на 1:

    if even(k) # k - четное
        k ÷= 2
        p *= p # т.к. p^k = (p*p)^k*(t/2)
    else
        k -= 1
        t *= p # т.к. p^k * t = p^(k-1)*(p*t)
    end

В итоге получаем искомый алгоритм в следующем виде.

k, t, p = n, 1, a # k=n; t=1; p=a

#ИНВАРИАНТ: p^k*t=a^n 
while k>0
    if even(k) # k - четное
        k ÷= 2
        p *= p # т.к. p^k = (p*p)^k*(t/2)
    else
        k -= 1
        t *= p # т.к. p^k * t = p^(k-1)*(p*t)
    end   
end
#УТВ: t = a^n

Алгоритм вычисления логарифма числа (без использования разложения логарифмической функции в степенной ряд)

Пиусть требуется построить алгоритм приближенного вычисления $log_ax$ для произвольного заданного положительного числа $x$.

Пусть задано $varepsilon&gt;0)$ — максимально допустимая погрешность вычислений, т.е. пусть требуется найти $y: |log_ax-y| le varepsilon$.

Положим $y^prime=log_ax$ (неизвестное нам точное значение логарифма), и $Delta = y^prime-y$ (величина погрешности), тогда
$$
x=a^{y + Delta}=a^{y} a^{Delta}
$$
Положим теперь $a^Delta=z^t$, где $z$, $t$ — две новые независимые переменные, тогда
$$
x=a^{y}z^t
$$
Прологарифмировав это тождество по основанию $a$, получим:
$$
y^prime=y + t cdot log_az,
$$
откуда следует
$$
|Delta|=|t|cdot|log_az|levarepsilon.
$$
Чтобы обеспечить выполнение этого неравенства достаточно добиться, чтобы было $|t|levarepsilon$ и $|log_az|le 1$.

Ограничимся, для определенности, случаем $a&gt;1$, тогда неравенство $|log_az|le 1$ равносильно двойному неравенству $1/a le z le a$.

Таким образом имеем следующие 3 фазовых переменных y, z, t, которые должны быть связаны между собой следующим инвариантным по отношению итерациям соотношением
$$
a^{y}z^t=x.
$$
Если в качестве начального значения положить $z=x$, $t=1$, то получим $a^y=1$, т.е. $y=0$.

И так, искомый алгоритм будет иметь вид:

z, t, y = x, 1, 0 # z=x; t=1.0; y=0.0
#ИНВАРИАНТ: a^y * z^t == x (=const)
while !(1/a <= z <= a && abs(t)<=1)
    ....
end

В переобразования фазовых переменных в теле цикла должны быть направлены на достижение условия (1/a <= z <= a && abs(t)<=1) при условии соблюдения инварианта. Условие (1/a <= z <= a && abs(t)<=1) состоит из двух отдельных условий, связанных «логическим И». Поэтому если хотя бы одно из двух не выполнено, то цикл должен продолжаться. Если не будет выполнено условие abs(t)<=1, фазовую переменную t нужно будет уменьшать, например, в 2 раза. А если не будет выполнено условие 1/a <= z <= a, то переменную z надо или увеличивать в a раз, или, наоборот, уменьшать в a раз — в зависимости от того, какое именно из двух неравенств в этом двойном неравенстве не выполняется.

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

z, t, y = x, 1, 0
#ИНВАРИАНТ: a^y * z^t == x (=const)
while z > a || z < 1/a || t > ε   
    if z > a
        z /= a
        y += t # т.к. z^t = (z/a)^t * a^t
    elseif z < 1/a
        z *= a
        y -= t # т.к. z^t = (z*a)^t * a^-t
    else # t > ε
        t /= 2
        z *= z # т.к. z^t = (z*z)^(t/2)
    end
end
#УТВ: y: |log_a(x)-y| <= ε

Замечание. В этом алгоритме последовательность, в которой проверяются условия z > a, z < 1/a, t > ε существенна, так если проверку начинать с условия t > ε, то возможен неприятный эффект, приводящий к грубым ошибкам, если только при этом значение величины z окажется далеко за пределами интервала [1/a; a], т.к. в этом случае преобразование z *= z будет еще дальше уводить величину z от целевого интервала.

Наибольший общий делитель двух целых чисел

Пусть a, b — целые числа.

Их наибольший общий делитель, НОД(a,b) — это наибольшее положительное целое, являющееся делителем обоих чисел.

При этом дополнительно считается, что НОД(0,0)=0.

Ясно что,

  • НОД(a,b) = НОД(b,a)
  • для любого целого a НОД(a,1)=1
  • для любого целого a НОД(a,0)=a
  • для любых целых a, b НОД(a,b) = НОД(a, -b)
  • для любых целых a, b НОД(a,b) = НОД(a,a+b) = НОД(a, a-b)

Алгоритм Евклида

# m, n - заданные целые
a, b = m, n
#ИНВАРИАНТ: НОД(a,b)==НОД(m,n)
while b != 0
    a, b = b, a % b # a % b - целочисленный остаток от деления a на b
end
#УТВ: b == НОД(m,m)

Замечание. В этом варианте алгоритма, если не ограничиваться только положителными a, b, ответ может получиться оррицательным, что легко поправить, взяв абсолютную величину.

Расширенный алгоритм Евклида

Теорема. Для любых двух целых чисел a, b cуществуют целые u, v, такие что НОД(a,b) = u*a + v*b.

Мы докажем эту теорему, спроектировав соответствующий алгоритм, основываясь на методе инварианта цикла.

Алгоритм, подобный алгоритму Евклида, который наряду с НОД(a,b) вычисляет также и названные целые числа u,v, называется расширенным алгоритмом Евклида.

Для его проектирования применим метод инварианта цикла.

# m, n - заданные целые
a, b = m, n
u_a, v_a = 1, 0
u_b, v_b = 0, 1
#=
ИНВАРИАНТ: 
    НОД(m,n)==НОД(a,b)
    a = u_a*m + v_a*n 
    b = u_b*m + v_b*n
=#

while b != 0
    k = a÷b
    a, b = b, a % b 
    #УТВ: a % b = a-k*b - остаток от деления a на b
    u, v = u_a, v_a
    u_a, v_a = u_b, u_a
    u_b, v_b = u-k*u_b, v-k*v_b
end
#УТВ: b == НОД(m,m) == u_a*m + v_a*n

Тем самым теорема доказана.

Замечания.

  1. На каждом шаге расширенного алгоритма Евклида требуется вычислять частное и остаток от деления целых чисел. Однако в языке Julia имеется встроенная функци divrem позволяющая получать и частное и остаток всего за одну операцию. С использование этой функции следующие строчки кода с двумя операциями % и ÷

могут быть заменены на код с одной единственной операцией divrem следущим образом:

k, r = divrem(a,b)
a, b = b, r 

что является предпочтительным.

  1. В приведенном варианте расширеннного алгоротитма Евклида, также как и в рассмотренном выше простом алгоритме Евклида, не учтена возможность отрицательных значений чисел a, b. Но это очень легко поправить, только теперь, если понадобится изменять знак полученного наибольшего (по модулю) общего делителя с отрицательного на положительный, одновременно с этим должны изменияться знаки и коэффициентов u_a, v_a.

Вычисление обратного элемента в кольце вычетов по модулю $n$

Практическая важность расширенного алгоритма Евклида состоит в том, что с его помощью можно находить обратные элементы в кольце вычетов по модулю $n$.

Как известно, элемент $m$ обратим в кольце вычетов по модулю $n$, если числа $m$, $n$ взаимно простые, т.е. если $НОД(m,n)=1$.

Таким образом, если
$$НОД(m,n) = um + vn,$$
и если $НОД(m,n)=1$, то
$$um + vn=1,$$
или
$$u*mequiv 1 (mod n),$$
т.е. если $m in mathbb{Z_n}$, то
$$m^{-1} = u (mod n).$$

Решение нелинейного уравнения методом деления отрезка пополам

Рассмотрим уравнение вида
$$f(x)=0,$$
где $f: [a;b]to mathbb{R}$ — некоторая непрерывная на отрезке $[a;b]$ функция, и при этом выполнены следующие два условия:

  • на открытом интервале $(a;b)$ уравнение имеет ровно один корень (этот интервал называют интервалом локализации корня);
  • на концах $[a;b]$ значения функции имеют противоположные знаки, т.е. $f(a)cdot f(b)&lt;0$.

Пусть задана максимально допустимая абсолютная погрешность $varepsilon&gt;0$, с которой требуется вычислить значение корня. Тогда задача сводится к тому, чтобы найти такой отрезок $[a^prime; b^prime]$, чтобы, во-первых, он содержал корень, и, во-вторых, его длина не превосходила бы величины $varepsilon$. Тогда любую точку этого отрезка, например, его середину, можно принять за искомое приближенное решение уравнения.

Идея метода деления отрезка пополам для приближенного решения данного уравнения выражается в следующих пунктах:

  • вычислить функцию в средне отрезка локализации корня;
  • сравнивать знак полученного значения со знаком функции в одном из концов отрезка локализации, например, со значением на левом его конце;
  • если знаки окажутся совпадающими, то левую половину отрезка локализации можно смело отбросить (там заведомо корня нет) и переместить левую границу отрезка локализации в среднюю его точку;
  • если же знаки окажутся противоположными, то, наоборот, правую половину отрезка следует отбросить (т.к. корень только один), и правую границу отрезка локализации переместить на его середину.

Перечисленные пункы следует повторять до тех пор, пока длина отрезка локализации превышает заданую максимально допустимую погрешность.

Следующий рисунок иллюстрирует первые 2 шага метода деления отрезка пополам fig-2

Таким образом, если переменные $a$, $b$ считать фазовыми переменными цикла (изменяющимися в этом цикле), то условие $f(a)cdot f(b)&lt;0$ должно рассматриваться как его инвариант. При этом условие $b-a&gt;varepsilon$ есть условие продолжения цикла.

Соответствующая функция на языке Julia могла бы выглядеть так:

function bisect(f::Funcnion, a, b, ε)
    y_a=f(a)
    # ИНВАРИАНТ: f(a)*f(b) < 0 (т.е. (a,b) - содержит корень)
    while b-a > ε
        x_m = (a+b)/2
        y_m=f(x_m)
        if y_m==0
            return x_m
        end
        if y_m*y_a > 0 
            a=x_m
        else
            b=x_m
        end
    end
    return (a+b)/2
end

Вычислительная сложность рассмотренного алгоритма оценивается, очевидно, как $O(log((b-a)/varepsilon)$, при $varepsilon to 0$.

Обратное по модулю целого a — это такое целое число x, что произведение ax сравнимо с 1 по модулю m[1]. В стандартных обозначениях модульной арифметики эта эквивалентность записывается как:

[math]displaystyle{ ax equiv 1 pmod{m}, }[/math]

что является сокращённым способом записи утверждения, что m делит (без остатка) величину ax − 1, или, выражаясь другим способом, остаток от деления ax на целое m равен 1. Если a имеет обратный по модулю m, то имеется бесконечное количество решений этой эквивалентности, которые образуют класс вычетов для этого модуля. Более того, любое целое, которое эквивалентно a (то есть из класса эквивалентности a) будет иметь любой элемент класса эквивалентности x в качестве обратного элемента. Используя обозначения [math]displaystyle{ overline{w} }[/math] для класса эквивалентности, содержащего [math]displaystyle{ w }[/math], утверждение выше может быть записано следующим образом: обратный элемент по модулю класса эквивалентности [math]displaystyle{ overline{a} }[/math] есть класс эквивалентности [math]displaystyle{ overline{x} }[/math], такой что

[math]displaystyle{ overline{a}cdot_{m} overline{x} = overline{1}, }[/math]

где символ [math]displaystyle{ cdot_m }[/math] означает умножение классов эквивалентности по модулю m[2]. Такой вид записи представляет аналог обычной концепции обратного числа в множестве рациональных или вещественных чисел, если заменить числа классами эквивалентности и должным образом определения бинарных операций.

Фундаментальное использование этой операции — решение линейной эквивалентности вида:

[math]displaystyle{ ax equiv b pmod{m}. }[/math]

Нахождение модульного обратного имеет практическое приложение в области криптографии, например, криптосистема с открытым ключом и алгоритм RSA [3][4][5]. Преимущество для реализации этих приложений в том, что существует очень быстрый алгоритм (расширенный алгоритм Евклида), который может быть использован для вычисления модульных обратных.

Модульная арифметика

Говорят, что для данного положительного числа m два целых числа a и b сравнимы по модулю m, если m делит их разность. Это бинарное отношение обозначается как

[math]displaystyle{ a equiv b pmod{m}. }[/math]

Это является отношением эквивалентности на множестве целых чисел [math]displaystyle{ mathbb{Z} }[/math], и классы эквивалентности называются классами вычетов по модулю m. Пусть [math]displaystyle{ overline{a} }[/math] означает класс эквивалентности, содержащий целое число a[6], тогда

[math]displaystyle{ overline{a} = {b in mathbb{Z} mid a equiv b pmod{m} }. }[/math]

Линейное сравнение — это сравнение по модулю вида

[math]displaystyle{ ax equiv b pmod{m}. }[/math]

В отличие от линейных уравнений в целых числах, линейное сравнение может иметь ноль, одно или несколько решений. Если x является решением линейного сравнения, то любой элемент из [math]displaystyle{ overline{x} }[/math] также является решением, так что, если говорится о количестве решений линейного сравнения, подразумевается количество различных классов эквивалентности, которые содержат эти решения.

Если d является наибольшим общим делителем чисел a и m, то линейное сравнение [math]displaystyle{ ax equiv b pmod{m} }[/math] имеет решения тогда и только тогда, когда d делит b. Если d делит b, то существует ровно d решений[7].

Модульное обратное целого числа a по модулю m — это решение линейного сравнения

[math]displaystyle{ ax equiv 1 pmod{m}. }[/math]

Ранее говорилось, что решение существует тогда и только тогда, когда наибольший общий делитель a и m равен 1, то есть a и m должны быть взаимно простыми числами. Более того, если это условие выполняется, существует ровно одно решение, то есть, если решение существует, модульное обратное единственно[8].

Если [math]displaystyle{ axequiv 1 pmod{m} }[/math] имеет решение, оно обозначается часто следующим образом

[math]displaystyle{ x equiv a^{-1} pmod{m}, }[/math]

однако это можно считать злоупотреблением[en], поскольку может неверно интерпретироваться как обычное обратное числа [math]displaystyle{ a }[/math] (которое, в отличие от модульного обратного, не является целым за исключением случаев, когда a равно 1 или -1). Обозначение было бы приемлемым, если бы a интерпретировался как обозначение для класса вычетов [math]displaystyle{ overline{a} }[/math], поскольку обратный элемент класса вычетов снова является классом вычетов с операцией умножения, определённой в следующем разделе.

Целые по модулю m

Отношение эквивалентности по модулю m разбивает множество целых чисел на m классов эквивалентности. Операции сложения и умножения можно определить на этих объектах следующим образом: для сложения или умножения классов эквивалентности сначала любым способом выбираются представители этих классов, затем осуществляется обычная операция над отобранными целыми числами и, наконец, результат операции лежит в классе вычетов, являющемся результатом операции над классами. В символической форме, с [math]displaystyle{ +_m }[/math] и [math]displaystyle{ cdot_m }[/math] представляющими операции над классами вычетов, эти определения можно записать как

[math]displaystyle{ overline{a} +_m overline{b} = overline{a + b} }[/math]

и

[math]displaystyle{ overline{a} cdot_m overline{b} = overline{ab}. }[/math]

Эти операции вполне определены (что означает, что конечный результат не зависит от выбора представителей).

Классы вычетов по m с этими двумя операциями образуют кольцо, называемое кольцом целых чисел по модулю m. Имеется несколько обозначений, используемых для этих алгебраических объектов, наиболее часто используется [math]displaystyle{ mathbb{Z}/mmathbb{Z} }[/math] или [math]displaystyle{ mathbb{Z}/m }[/math], однако некоторые элементарные учебники и приложения используют упрощённое обозначение [math]displaystyle{ mathbb{Z}_m }[/math], если не возникает противоречие с другими алгебраическими объектами.

Классы вычетов целых чисел по модулю m были традиционно известны как классы остатков по модулю m, что отражает факт, что все элементы класса эквивалентности имеют один и тот же остаток от деления на m. Любое множество из m целых, выбранных из разных классов вычетов по модулю m называется полной системой вычетов по модулю m[9]. Деление столбиком показывает, что множество целых чисел {0, 1, 2, …, m − 1} образуют полную систему вычетов по модулю m, известную как наименьшая система вычетов по модулю m. При работе с арифметическими задачами иногда удобнее работать с полной системой вычетов и использовать язык эквивалентности, в то время как в других случаях более удобен взгляд с точки зрения классов эквивалентности кольца [math]displaystyle{ mathbb{Z}/mmathbb{Z} }[/math][10].

Мультипликативная группа кольца вычетов

Не всякий элемент полной системы вычетов по модулю m имеет обратный элемент, например, нуль обратного не имеет. После удаления элементов полной системы вычетов, что не взаимно просты с m, оставшиеся элементы, которые называются приведённой системой вычетов, все имеют обратные. Число элементов в приведённой системе вычетов равно [math]displaystyle{ phi(m) }[/math], где [math]displaystyle{ phi }[/math] есть функция Эйлера, то есть количество положительных целых чисел меньших m, которые взаимно просты с m.

В кольце с единицей общего вида не всякий элемент имеет обратный, а те, что имеют, называются обратимыми. Поскольку произведение обратимых элементов обратимо, обратимые элементы кольца образуют группу, группу обратимых элементов кольца, и эта группа часто обозначается как [math]displaystyle{ R^{times} }[/math], если R является названием кольца. Группа обратимых элементов кольца целых чисел по модулю m называется мультипликативной группой целых по модулю m, и она изоморфна приведённой системе вычетов. В частности, её порядок (размер) равен [math]displaystyle{ phi(m) }[/math].

Когда m является простым, скажем p, то [math]displaystyle{ phi(p) = p-1 }[/math] и все ненулевые элементы [math]displaystyle{ mathbb{Z}/pmathbb{Z} }[/math] имеют обратные, а тогда [math]displaystyle{ mathbb{Z}/pmathbb{Z} }[/math] является конечным полем. В этом случае мультипликативная группа целых чисел по модулю p образует циклическую группу порядка p − 1.

Пример

Для иллюстрации вышеприведённых определений рассмотрим пример чисел по модулю 10.

Два числа эквивалентны по 10 тогда и только тогда, когда их разность делится на 10, например

[math]displaystyle{ 32 equiv 12 pmod{10} }[/math] поскольку 10 делит 32 − 12 = 20,
[math]displaystyle{ 111 equiv 1 pmod{10} }[/math] поскольку 10 делит 111 − 1 = 110.

Некоторые из классов вычетов по этому модулю:

[math]displaystyle{ overline{0} = { cdots, -20, -10, 0, 10, 20, cdots } }[/math]
[math]displaystyle{ overline{1} = { cdots, -19, -9, 1, 11, 21, cdots } }[/math]
[math]displaystyle{ overline{5} = { cdots, -15, -5, 5, 15, 25, cdots } }[/math]
[math]displaystyle{ overline{9} = { cdots, -11, -1, 9, 19, 29, cdots }. }[/math]

Линейное сравнение [math]displaystyle{ 4x equiv 5 pmod{10} }[/math] не имеет решений, поскольку целые, конгруэнтные 5 (то есть, входящие в [math]displaystyle{ overline{5} }[/math]) все нечётные, в то время как 4x все чётные. Однако линейное сравнение [math]displaystyle{ 4x equiv 6 pmod{10} }[/math] имеет два решения, а именно, [math]displaystyle{ x=4 }[/math] и [math]displaystyle{ x=9 }[/math]. НОД(4, 10) = 2 и 2 не делит 5, но делит 6.

Поскольку НОД(3, 10) = 1, линейное сравнение [math]displaystyle{ 3xequiv 1 pmod{10} }[/math] будет иметь решения, то есть, модульное обратное числа 3 по модулю 10 будет существовать. 7 удовлетворяет этому уравнению (21 − 1 = 20). Однако и другие целые удовлетворяют этому уравнению, например 17 и −3 (поскольку 3(17) − 1 = 50 и 3(−3) − 1 = −10). В частности, любое целое число из [math]displaystyle{ overline{7} }[/math] будет удовлетворять уравнению, поскольку эти числа имеют вид 7 + 10r для некоторого r и ясно, что

[math]displaystyle{ 3(7 + 10 r) — 1 = 21 + 30 r -1 = 20 + 30 r = 10(2 + 3r), }[/math]

делится на 10. Это уравнение имеет только один класс вычетов в качестве решений. Решение в этом случае может быть получено просто перебором возможных классов, но для получения решения для больших модулей нужны систематические алгоритмы, и они будут представлены в следующих разделах.

Произведение классов вычетов [math]displaystyle{ overline{5} }[/math] и [math]displaystyle{ overline{8} }[/math] может быть получено путём выбора элемента из [math]displaystyle{ overline{5} }[/math], скажем 25, и элемента из [math]displaystyle{ overline{8} }[/math], скажем −2, и их произведение (25)(−2) = −50 находится в классе эквивалентности [math]displaystyle{ overline{0} }[/math]. Таким образом, [math]displaystyle{ overline{5} cdot_{10} overline{8} = overline{0} }[/math]. Сложение определяется аналогично. Десять классов вычетов вместе с этими операциями сложения и умножения классов вычетов образует кольцо целых чисел по модулю 10, то есть [math]displaystyle{ mathbb{Z}/10mathbb{Z} }[/math].

Полной системой вычетов по модулю 10 может быть множество {10, −9, 2, 13, 24, −15, 26, 37, 8, 9}, где каждое целое лежит в своём классе вычетов по модулю 10. Минимальной системой вычетов по модулю 10 служит {0, 1, 2, …, 9}. Приведённой системой вычетов по модулю 10 может быть {1, 3, 7, 9}. Произведение любых двух классов вычетов, представленных этими числами, снова является один из этих четырёх классов. Из этого следует, что эти четыре класса вычетов образуют группу, в этом случае циклическую группу порядка 4, имеющую в качестве генератора 3 или 7. Представленные классы вычетов образуют группу обратимых элементов кольца [math]displaystyle{ mathbb{Z}/10mathbb{Z} }[/math]. Эти классы вычетов в точности те, что имеют обратные по модулю.

Вычисление

Расширенный алгоритм Евклида

Модульное обратное для числа a по модулю m можно найти с помощью расширенного алгоритма Евклида.

Алгоритм Евклида определяет наибольший общий делитель (НОД) двух целых чисел, скажем a и m. Если a имеет обратное по модулю m число, этот НОД должен быть равен 1. Несколько последних равенств, получаемых в процессе работы алгоритма, могут быть решены для нахождения НОД. Затем, используя метод «обратной подстановки», может быть получено выражение, связывающее исходные параметры и НОД. Другими словами, могут быть найдены целые x и y, удовлетворяющие равенство Безу,

[math]displaystyle{ ax + my = text{НОД }(a, m)= 1. }[/math]

Перепишем это следующим образом

[math]displaystyle{ ax — 1 = (-y)m, }[/math]

то есть,

[math]displaystyle{ ax equiv 1 pmod{m}, }[/math]

и модульное обратное числа a вычислено. Более эффективной версией является расширенный алгоритм Евклида, который с помощью дополнительных равенств сокращает два прохода алгоритма (обратную подстановку можно понимать как прохождение алгоритма в обратном порядке) до одного.

В нотации O большое этот алгоритм работает за время [math]displaystyle{ O(log(m)^2) }[/math] в предположении, что [math]displaystyle{ |a| lt m }[/math], и считается очень быстрым. Он обычно более эффективен чем альтернативный экспоненциальный алгоритм.

Использование теоремы Эйлера

В качестве альтернативы расширенному алгоритму Евклида для вычисления модульного обратного элемента можно рассматривать использование теоремы Эйлера[11].

Согласно теореме Эйлера, если a взаимно просто с m, то есть НОД(a, m) = 1, то

[math]displaystyle{ a^{phi(m)} equiv 1 pmod{m}, }[/math]

где [math]displaystyle{ phi }[/math] — функция Эйлера. Это следует из факта, что a принадлежит мультипликативной группе [math]displaystyle{ (mathbb{Z}/mmathbb{Z})^{times} }[/math] тогда и только тогда, когда a взаимно просто с m. Таким образом, модульное обратное можно найти напрямую:

[math]displaystyle{ a^{phi(m)-1} equiv a^{-1} pmod{m}. }[/math]

В специальном случае, когда m простое, [math]displaystyle{ phi (m) = m — 1 }[/math] и модульное обратное задаётся равенством

[math]displaystyle{ a^{-1} equiv a^{m-2} pmod{m}. }[/math]

Этот метод, как правило, медленнее расширенного алгоритма Евклида, но иногда используется, если реализация для модульного возведения в степень уже доступна. Недостатки этого метода:

  • Значение [math]displaystyle{ phi (m) }[/math] должно быть известно, а наиболее эффективный метод вычисления требует m разложений. Разложение хорошо известно как задача, в которой вычисления занимают большую часть сложности решения. Однако вычислить [math]displaystyle{ phi (m) }[/math] можно непосредственно, если известно разложение на простые множители числа m.
  • Относительно высокая стоимость возведения в степень. Хотя это можно реализовать более эффективно с помощью модульного возведения, при больших значениях m наиболее эффективен метод алгоритма Монтгомери. Этот алгоритм сам по себе требует вычисления обратного по модулю m. Без алгоритма Монтгомери стандартный бинарный алгоритм возведения, который требует деления по модулю m на каждом шаге, является медленной операцией при большом m.

Замечательное преимущество этой техники в том, что нет условных ветвлений, которые зависят от значения a, а потому значение a, которое может быть важным секретом в криптосистемах с открытым ключом, может быть защищено от атак по сторонним каналам. По этой причине стандартная реализация Curve25519 использует технику вычисления обратного элемента.

Вычисление нескольких обратных

Можно вычислить обратные для нескольких чисел [math]displaystyle{ a_i }[/math] по общему модулю m используя один проход алгоритма Евклида и три умножения на каждое дополнительное входное число[12]. Основной идеей является образование всех [math]displaystyle{ a_i }[/math], обращение его, а затем умножение на [math]displaystyle{ a_j }[/math] для всех [math]displaystyle{ jne i }[/math], чтобы остался только [math]displaystyle{ a^{-1}_i }[/math].

Алгоритм (вся арифметика осуществляется по модулю m):

  1. Вычисляем префиксные произведения [math]displaystyle{ b_i = prod_{j=1}^i a_j = a_i b_{i-1} }[/math] для всех [math]displaystyle{ i leqslant n }[/math].
  2. Вычисляем [math]displaystyle{ b^{-1}_n }[/math] с помощью любого доступного алгоритма.
  3. Для i от n до 2 вычисляем
    • [math]displaystyle{ a^{-1}_i =b^{-1}_ib_{i-1} }[/math] и
    • [math]displaystyle{ b^{-1}_{i-1} =b^{-1}_ia_i }[/math].
  4. Наконец, [math]displaystyle{ a^{-1}_1=b^{-1}_1 }[/math].

Можно осуществить умножение в виде древесной структуры, а не линейной, чтобы обеспечить параллельность вычислений.

Приложения

Поиск модульного обратного имеет много приложений в алгоритмах, опирающихся на теорию модульной арифметики. Например, в криптографии использование модульной арифметики позволяет осуществлять некоторые операции быстрее и с меньшими требованиями к памяти, в то время как другие операции становится выполнить труднее[13]. Оба этих свойства могут использоваться во благо. В частности, в алгоритме RSA шифрование и обратный этому процесс сообщения делается с помощью пары чисел, обратных друг другу по некоторому тщательно выбранному модулю. Один из этих чисел делается открытым, и он может быть использован в быстрой процедуре шифрования, в то время как другое число используется в процедуре расшифровки и не разглашается. Определение скрытого ключа по открытому считается невыполнимой задачей, так как вычислительной мощности на её решение требуется больше, чем есть на Земле, что и защищает от несанкционированного доступа[14].

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

  1. Используем расширенный алгоритм Евклида для вычисления [math]displaystyle{ k^{-1} }[/math], модульного обратного [math]displaystyle{ k pmod{2^w} }[/math], где w равно числу бит в слове. Это обратное существует, поскольку все числа нечётные, а рассматриваются вычеты по модулю, не имеющему нечётных делителей.
  2. Каждое число в списке умножаем на [math]displaystyle{ k^{-1} }[/math] и выбираем наименее значащие биты результата (то есть отбрасываем все биты за пределами компьютерного слова).

Во многих машинах, в частности тех, у которых нет аппаратной поддержки деления, деление является более медленной операцией, чем умножение, так что этот подход может повлечь существенное увеличение скорости. Первый шаг относительно медленный, но его нужно сделать всего один раз.

Модульные обратные числа используются для получения решения системы линейных сравнений, что гарантируется китайской теоремой об остатках.

Например, система

[math]displaystyle{ begin{cases}
X equiv 4 pmod{5} \
X equiv 4 pmod{7} \
X equiv 6 pmod{11} \
end{cases} }[/math]

имеет общее решение, поскольку 5, 7 и 11 попарно взаимно просты. Решение даётся формулой

[math]displaystyle{ X=t_1 (7 times 11) times 4+t_2 (5times 11)times 4+t_3 (5times 7)times 6 }[/math]

где

[math]displaystyle{ t_1= 3 }[/math] модульное обратное [math]displaystyle{ 7times11 pmod{5} }[/math],
[math]displaystyle{ t_2=6 }[/math] модульное обратное [math]displaystyle{ 5times11 pmod{7} }[/math],
[math]displaystyle{ t_3=6 }[/math] модульное обратное [math]displaystyle{ 5times7 pmod{11} }[/math].

Тогда,

[math]displaystyle{ X=3times(7times 11) times 4 + 6 times (5 times 11) times 4 + 6 times (5 times 7) times 6= 3504 }[/math]

и в приведённом виде

[math]displaystyle{ Xequiv 3504 equiv 39 pmod{385} }[/math]

поскольку 385 является наименьшим общим кратным чисел 5, 7 и 11.

Модульное обратное фигурирует на видном месте в определении сумм Клоостермана.

См. также

  • Инверсный конгруэнтный метод — алгоритм генерации псевдослучайных чисел, использующий обратные по модулю числа.
  • Восстановление рационального числа по его модулю[en]

Примечания

  1. Rosen, 1993, с. 132.
  2. Schumacher, 1996, с. 88.
  3. Stinson, 1995, с. 124–128.
  4. Trappe, Washington, 2006, с. 164−169.
  5. Moriarty, K.; Kaliski, B.; Jonsson, J.; Rusch, A. PKCS #1: RSA Cryptography Specifications Version 2.2. Internet Engineering Task Force RFC 8017. Internet Engineering Task Force (2016). Дата обращения: 21 января 2017. Архивировано 12 декабря 2018 года.
  6. Other notations are often used, including [a] and [a]m.
  7. Ireland, Rosen, 1990, с. 32.
  8. Shoup, 2005, с. 15 Theorem 2.4.
  9. Rosen, 1993, с. 121.
  10. Ireland, Rosen, 1990, с. 31.
  11. Koshy, 2007, с. 346.
  12. Brent, Zimmermann, 2010, с. 67–68.
  13. Trappe, Washington, 2006, с. 167.
  14. Trappe, Washington, 2006, с. 165.

Литература

  • Douglas R. Stinson. Cryptography / Theory and Practice. — CRC Press, 1995. — ISBN 0-8493-8521-0.
  • Victor Shoup. A Computational Introduction to Number Theory and Algebra. — Cambridge University Press, 2005. — ISBN 9780521851541.
  • Thomas Koshy. Elementary number theory with applications. — 2nd edition. — Academic Press, 2007. — ISBN 978-0-12-372487-8.
  • Richard P. Brent, Paul Zimmermann. §2.5.1 Several inversions at once // Elementary number theory with applications. Modern Computer Arithmetic. — Cambridge University Press, 2010. — Т. 18. — (Cambridge Monographs on Computational and Applied Mathematics). — ISBN 978-0-521-19469-3.
  • Kenneth Ireland, Michael Rosen. A Classical Introduction to Modern Number Theory. — 2nd. — Springer-Verlag, 1990. — ISBN 0-387-97329-X.
    • К. Айерлэнд, М. Роузен. Классическое введение в современную теорию чисел / Перевод с английского С. П. Демушкина. — Москва: «Мир», 1987.
  • Kenneth H. Rosen. Elementary Number Theory and its Applications. — 3rd. — Addison-Wesley, 1993. — ISBN 978-0-201-57889-8.
  • Carol Schumacher. Chapter Zero: Fundamental Notions of Abstract Mathematics. — Addison-Wesley, 1996. — ISBN 0-201-82653-4.
  • Wade Trappe, Lawrence C. Washington. Introduction to Cryptography with Coding Theory. — 2nd. — Prentice-Hall, 2006. — ISBN 978-0-13-186239-5.

Ссылки

  • Weisstein, Eric W. Modular Inverse (англ.) на сайте Wolfram MathWorld.
  • Геварра Васкез, Фернандо предлагает пример решения обратного по модулю с помощью Евклидова Алгоритма.

Понравилась статья? Поделить с друзьями:

Не пропустите также:

  • Как найти степень с основанием в дроби
  • Как составить смету по экономике
  • Как найти врага во сне
  • Как найти расчетный счет рнкб
  • Как найти музыку шазам с телефона

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии