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

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

пререквизиты Алгоритм Евклида

Просто для нахождения gcd\gcd даже не нужно знать, как устроен алгоритм Евклида — он есть в компиляторе.

Расширенный алгоритм Евклида находит, помимо g=gcd(a,b)g = \gcd(a, b), такие целые коэффициенты xx и yy, что

ax+by=g a \cdot x + b \cdot y = g

Заметим, что решений бесконечно много: имея решение (x,y)(x, y), можно xx увеличить на bb, а yy уменьшить на aa, и равенство при этом не изменится.

#Основная идея

Алгоритм тоже будет рекурсивный. Пусть мы посчитали нужные коэффициенты xx’ и yy’, когда рекурсивно считали gcd(b,amodb)\gcd(b, a \bmod b). Иными словами, у нас есть решение (x,y)(x’, y’) для пары (b,amodb)(b, a \bmod b):

bx+(amodb)y=g b \cdot x' + (a \bmod b) \cdot y' = g Чтобы получить решение для исходной пары, запишем выражение (amodb)(a \bmod b) по определению как (aabb)(a - \lfloor \frac{a}{b} \rfloor \cdot b) и подставим в приведенное выше равенство: bx+(aabb)y=g b \cdot x' + (a - \Big \lfloor \frac{a}{b} \Big \rfloor \cdot b) \cdot y' = g Теперь выполним перегруппировку слагаемых (сгруппируем по исходным aa и bb) и получим: ayx+b(xaby)y=g a \cdot \underbrace{y'}_x + b \cdot \underbrace{(x' - \Big \lfloor \frac{a}{b} \Big \rfloor \cdot y')}_y = g

Сравнивая это с исходным выражением, получаем, что для исходных xx и yy подходят коэффициенты при aa и bb.

#Реализация

int gcd(int a, int b, int &x, int &y) {
    if (a == 0) {
        x = 0;
        y = 1;
        return b;
    }
    int x1, y1;
    int d = gcd(b % a, a, x1, y1);
    x = y1 - (b / a) * x1;
    y = x1;
    return d;
}

Эта рекурсивная функция по прежнему возвращает значение gcd(a,b)\gcd(a, b), но помимо этого записывает в переданные по ссылке переменные xx и yy искомые коэффициенты.

#Применения

Эта модификация алгоритма интересна, потому что с помощью неё можно искать обратный элемент по модулю: такой элемент a1a^{-1}, что aa11a \cdot a^{1} \equiv 1 — что то же самое, что найти решение в целых числах:

a1a+km=1 a^{-1} \cdot a + k \cdot m = 1 Также с помощью расширенного алгоритма Евклида можно решать линейные диофантовы уравнения — находить решения ax+by=c a \cdot x + b \cdot y = c в целых числах. Для этого достаточно проверить, что cc делится на g=gcd(a,b)g = \gcd(a, b), и если это так, то xx и yy из алгоритма нужно просто домножить на cg\frac{c}{g}.