Fork me on GitHub

扩展欧几里得算法

裴蜀定理

对于任意一对正整数\(a,b\)一定存在\(x,y\)使得

\(ax+by = gcd(a, b)\)

  1. 其中最大公约数就是能凑出来的最小的整数

    因为\(ax+by = gcd(a, b)\),不论\(x, y\)怎么变化

    左边的式子加起来得到的结果就是最大公约数的倍数。

    而这个倍数最小是1.也就是最大公约数的情况

  2. \(b=0\)时, 有一组解是\(x=1, y=0\).

  3. 然后再递归定义。就可以得出来裴蜀定理的证明

扩展欧几里得算法

基本定义及推导

给定\(n\)对正整数\(ai,bi\),对于每对数,求出一组\(xi,yi\)

使其满足\(ai∗xi+bi∗yi=gcd(ai,bi)\)

首先,根据裴蜀定理,我们知道。这个一定能找到一组解

  1. \(a∗x+b∗y=gcd(a,b)\)
  2. \(a∗x+b∗y=gcd(b,a modb)\)
  3. \(b∗x+(a modb)∗y=gcd(b,a modb)\)
  4. \(b∗x+(a modb)∗y=gcd(a,b)\)
  5. \(b∗x+(a-b\lfloor{a/b}\rfloor)∗y=gcd(a,b)\)
  6. \(a∗y+b*(x-y\lfloor{a/b}\rfloor)=gcd(a,b)\)
  7. \(x^,= y, y^,=x-y\lfloor{a/b}\rfloor\)
  8. \(a∗x^,+b∗y^,=gcd(a,b)\)

递归结束的时候,也就是碰到了我们的边界条件

就可以算出来一个\(x, y\)

因为我们要改变\(x, y\)所以传参数的时候要通过传引用的方式来进行传达

代码

原始版

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, x, y);
    int z = x; x = y; y = z - (a/b)*y;
    return d;
}
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;


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;
}
int main()
{
    int n;
    cin >> n;
    while(n--)
    {
        int x, y, a, b;
        scanf("%d %d", &a, &b);
        exgcd(a, b, x, y); // 这里不用加取地址符号
        printf("%d %d\n", x, y);
    }
    return 0;
}
posted @ 2020-02-22 22:08  WalterJ726  阅读(199)  评论(0编辑  收藏  举报