Сегодня я попытаюсь разобрать алгоритм Евклида в его расширенном варианте. Что это значит? Что значит "расширенный"? Это просто. Вот мы нашли НОД(a,b)=d, но нам надо узнать вот что:
То есть, нам надо найти такой x и такой y, при умножении на которое у нас получится d (см. формулу выше). Вот пример. Найдем НОД(3,12) и он равен 3, потому что как 12, так и 3 делятся на 3. Хорошо, мы его нашли, выпишем:
Где a=3, b=12, d=НОД(3,12). И как теперь узнать, какие будут x, y? Автор классной книги, его звать Кнут (и пряник, ага), нашел этот отличный метод и назвал его "Расширенный алгоритм Евклида". Начнем по-порядку. Сначала надо вспомнить про алгоритм Евклида:
Где НОД(a,b) = НОД(b,r). Это было доказано ранее. Теперь посмотрим, как происходит обычно поиск НОД по этому алгоритму. Как мы помним, чтобы перейти к следующей итерации, надо разделить "a" на "b", получить q, и остаток, и применить их как новые "a" и "b".
Шаг
Поиск НОД
Разложение остатков
Описание
1
, теперь они вместо
2
, теперь они вместо
3
, теперь они вместо
4
, теперь они вместо
....
, теперь они вместо
Точка остановки
Все, что происходит тут – это просто магия. Обычная магия, которая происходит в фентези. Ложим в пробирку немного математических ингредиентов и начинаем смешивать. Немного выстоять... и зелье готово! Теперь немного придется включить воображение и приглядеться к формулам. Мы заметили, что:
И еще то, что:
И поэтому:
Давайте теперь подставим в формулу выше формулу ту, что ниже:
Раскроем скобки и перегруппируем:
Теперь приглядимся внимательно... так вот что мы видим? Мы видим, что коэффициентами перед a и b у нас стоят
и :
Да это просто шикарно! То есть, чтобы вычислить следующий и , нужно всего лишь знать предыдущие 2! Вот в этом и есть сила расширенного алгоритма Евклида.
Тут встает вопрос. Вот мы хотим вычислить и , то есть, нам нужны коэффициенты (, , ), и где их достать? А тут все просто. Взглянем на таблицу. У нас , то если мы попробуем найти , то в таком случае , и , судя по таблице.
Это значит, что:
Отсюда:
Вот такой вот он, расширенный алгоритм Евклида. И результатом НОД будет .
§ Программная реализация
А теперь время программного обеспечения.
// Расширенный НОД
int extnod(int a, int b, int* x, int* y) {
int q, r;
int x2 = 1, y2 = 0, // x(i-2)=1, y(i-2)=0
x1 = 0, y1 = 1; // x(i-1)=0, y(i-1)=1
do {
// Алгоритм Евклида
q = a / b;
r = a % b;
a = b;
b = r;
// Расширенный алгоритм Евклида
*x = x2 - x1*q; // x(i) = x(i-2) - x(i-1)*q
*y = y2 - y1*q; // y(i) = y(i-2) - y(i-1)*q
// "Сдвиг истории" назад
x2 = x1; y2 = y1; // Старый x(i-1), y(i-1) перемещается в x(i-2), y(i-2)
x1 = *x; y1 = *y; // Новый x(i), y(i) становится x(i-1), y(i-1)
} while (r > 0); // Перебирать, пока не станет r = 0
// И записать разультат, где x = x(i-1), y = y(i-1)
// т.к. ранее мы "сдвинули" в (x2, y2) старые (x1, y1)