扩展欧几里得算法笔记
扩展欧几里得算法笔记
什么是扩展欧几里得算法
扩展欧几里得算法是一种数论算法,其功能是求解这样一类二元线性不定方程:
\[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;
}