扩展欧几里得算法
裴蜀定理
法国数学家艾蒂安·裴蜀 Bézout 提出:指对于正整数
证明:首先我们知道,对于最大公约数
下面用 扩展欧几里得算法 进行构造性证明:
回忆欧几里得算法:
cpp
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
// addition
int gcd(int a, int b) {
if (b == 0) {
return a;
}
else {
return gcd(b, a % b);
}
}
核心代码:
cpp
int exgcd(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y = y - (a / b) * x;
return d;
}
边界情况下:此时一定是 ((a, b), 0)
。剩下的情况考虑递归,注意用引用传递 x, y
,当我们已经得到前面的系数之后,和欧几里得算法一样 a % b
照样可以使得方程成立,不过 x, y
会发生变化:
因此只需要修改 y
即可。
注意答案是有无穷组的,假设我们找到了一组
解集合:
TODO:是否所有的解都在这个解集合中呢?
线性同余方程
将这个问题转化为裴蜀等式:
求系数
核心代码:
cpp
if (b % d != 0) {
cout << "impossible" << endl;
}
else {
cout << (long long)x * (b / d) % m << endl;
}
注意这里的 b
不一定是最大公约数的倍数,得判断:
- 如果不是,直接输出
impossible
- 如果是,那么需要根据方程
进行扩充,得到 - 至于最后为什么要模
,是因为将 带入方程后 ,这样做可以避免 过大