拓展欧几里德算法
EXGCD
核心思想
这是一个求解 \(a * x + b * y = gcd(a, b)\) 方程的算法。
我们知道 \(a * x + b * y = gcd(a, b) = gcd(b, a \% b)\),对其展开,也就是。
-
\(a * x + b * y\)
-
\(= b * x + (a \% b) * y\)
-
\(= b * x + (a - a / b * b) * y\)
-
\(= a * y + (x - a / b * y) * b\)
当 \(b = 0\) 的时候也就是 \(a * x + b * y = gcd(a, b) = a\) 得到x = 1, y = 0
我们就是通过这个关系去不断地递归,最后求解得到这个方程组的解。
代码
/*
Code by lifehappy 2020:04:22
*/
#include<bits/stdc++.h>
using namespace std;
int exgcd(int a, int b, int &x, int &y) {
if(!b) {
x = 1;
y = 0;
return a;
}
int gcd = exgcd(b, a % b, x, y);
int temp = x;
x = y;
y = temp - a / b * y;
return gcd;
}
int main() {
int a, b, x, y;
while(cin >> a >> b) {
int gcd = exgcd(a, b, x, y);
printf("%d %d %d\n", gcd, x, y);
}
}
利用其求解二元一次方程
设有方程 \(a* x + b * y = c\)
我们知道这个方程有界的充要条件就是 \(gcd(a, b) \mid c\)
代码
/*
Code by lifehappy 2020:04:22
*/
#include<bits/stdc++.h>
using namespace std;
int exgcd(int a, int b, int &x, int &y) {
if(!b) {
x = 1;
y = 0;
return a;
}
int gcd = exgcd(b, a % b, x, y);
int temp = x;
x = y;
y = temp - a / b * y;
return gcd;
}
int main() {
int a, b, c, x, y;
while(cin >> a >> b >> c) {
int gcd = exgcd(a, b, x, y);
if(c % gcd) puts("NO ANSWER");
else printf("%d * %d + %d * %d = %d\n", a, c / gcd * x, b, c / gcd * y, c);
}
}