\(\rm EXGCD\),即 扩展欧几里得算法,简称 扩欧,是用来求出方程
\[ax+by=\gcd(a,b) \]的整数解的,其中 \(a,b\) 均为整数.
我们考虑辗转相除法的最后一步,当 \(b=0\) 时,要使得
\[ax+0y=\gcd(a,0)=a \]成立,那么只要取 \(x=1\),\(y\) 取任意整数即可,不妨取 \(y=0\).
因为 \(\gcd(a,b)=\gcd(b,a\bmod b)\),所以可以考虑当整数 \(x,y\) 使得
\[bx+(a\bmod b)y=\gcd(b,a\bmod b) \]成立时,如何推出使得
\[ax'+by'=\gcd(a,b) \]成立的 \(x',y'\).
对于 \(bx+(a\bmod b)y=\gcd(b,a\bmod b)\),
\(\begin{aligned}等式左边&=bx+(a-b\left\lfloor\frac{a}{b}\right\rfloor)y\\&=ay+b(x-\left\lfloor\frac{a}{b}\right\rfloor y)\end{aligned}\)
\(\begin{aligned}等式右边&=\gcd(a,b)\end{aligned}\)
所以要使 \(ax'+by'=\gcd(a,b)\) 的话,取 \(x'=y,y'=x-\left\lfloor\frac{a}{b}\right\rfloor y\) 即可。
就这样一直递归。
\(\text{Code}\)
int x, y;
void exgcd(int a, int b)
{
if (!b)
{
x = 1, y = 0;
return;
}
exgcd(b, a % b);
ll tmp = x; //先将 x 存下来
x = y;
y = tmp - a / b * y;
}