扩展欧几里得算法笔记

扩展欧几里得算法笔记

什么是扩展欧几里得算法

扩展欧几里得算法是一种数论算法,其功能是求解这样一类二元线性不定方程:

\[ax + by = c \]

这类方程有解的条件是\(\gcd(a, b) | c\)。这个结论依赖于裴蜀定理。扩展欧几里得算法能求出其一个基本形式的一组解,即:

\[ax + by = gcd(a, b) \]

接着可以通过变形获得这个基本形式的通解,而原方程的解可以通过按比例放大的方法获得。

补充:裴蜀定理

\(a, b\)是整数,且\(\gcd(a, b) = d\),那么对于任意的整数\(x, y\),\(ax + by\)都一定是d的倍数,特别地,一定存在整数\(x, y\),使\(ax + by = d\)成立。

这个定理的一个显然推论是:

“存在\(x, y\)使得\(ax + by = 1\)”与“\(a, b\)互质”互为充要条件。

因此扩展欧几里得算法可以用于求解乘法逆元。

算法思路

考虑一般的欧几里得算法(即辗转相除法),它的原理是:

\[\gcd(a, b) = \gcd(b, a\ mod\ b) \]

事实上

\[a\ mod\ b = a-b\lfloor\frac{a}{b}\rfloor \]

\[\gcd(a, b) = \gcd(b, a\ mod\ b) = \gcd(b, a-b\lfloor\frac{a}{b}\rfloor) \]

因此方程可以写作:

\[ax + by = \gcd(b, a - b\lfloor\frac{a}{b}\rfloor) \]

但是这样我们依然无法在求最大公约数的同时解出\(x,y\),所以考虑:

\[bx'+(a-b\lfloor\frac{a}{b}\rfloor)y' = \gcd(b, a - b\lfloor\frac{a}{b}\rfloor \]

这个方程和原来的方程实际上是同一种形式,于是我们可以在递归计算最大公约数的同时求解出\(x', y'\)。那么接下来的问题是,如何把\(x', y'\)变成\(x, y\)?很简单:

\[\because \gcd(b, a-b\lfloor\frac{a}{b}\rfloor) = \gcd(a, b) \]

\[\therefore bx'+(a-b\lfloor\frac{a}{b}\rfloor)y' = ax + by\text{恒成立} \]

移项以后我们得到:

\[x = y', y = x'-y'\lfloor\frac{a}{b}\rfloor \]

于是大功告成。

代码

#include <bits/stdc++.h>

int exgcd(int a, int b, int& x, int& y)
{
    if (a % b == 0)
    {
        x = 0; y = 1;
        return b;
    }
    int r = exgcd(b, a % b, x, y);
    int t = x;
    x = y;
    y = t - (a / b) * y;
    return r;
}

int main(void)
{
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    int x, y;
    int d = exgcd(a, b, x, y);

    if (c % d == 0)
    {
        x *= c / d; y *= c / d;
        printf("%d %d\n", x, y);
    }
    else
    {
        puts("No");
    }

    return 0;
}
posted @ 2022-07-21 22:59  kyEEcccccc  阅读(35)  评论(0编辑  收藏  举报