拓展欧几里德算法

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);
    }
}
posted @ 2020-04-22 22:25  lifehappy  阅读(148)  评论(0编辑  收藏  举报