扩展欧几里得算法
裴蜀定理
对于任意一对正整数\(a,b\)一定存在\(x,y\)使得
\(ax+by = gcd(a, b)\)
-
其中最大公约数就是能凑出来的最小的整数
因为\(ax+by = gcd(a, b)\),不论\(x, y\)怎么变化
左边的式子加起来得到的结果就是最大公约数的倍数。
而这个倍数最小是1.也就是最大公约数的情况
-
当\(b=0\)时, 有一组解是\(x=1, y=0\).
-
然后再递归定义。就可以得出来裴蜀定理的证明
扩展欧几里得算法
基本定义及推导
给定\(n\)对正整数\(ai,bi\),对于每对数,求出一组\(xi,yi\)
使其满足\(ai∗xi+bi∗yi=gcd(ai,bi)\)。
首先,根据裴蜀定理,我们知道。这个一定能找到一组解
- \(a∗x+b∗y=gcd(a,b)\)
- \(a∗x+b∗y=gcd(b,a modb)\)
- \(b∗x+(a modb)∗y=gcd(b,a modb)\)
- \(b∗x+(a modb)∗y=gcd(a,b)\)
- \(b∗x+(a-b\lfloor{a/b}\rfloor)∗y=gcd(a,b)\)
- \(a∗y+b*(x-y\lfloor{a/b}\rfloor)=gcd(a,b)\)
- 令\(x^,= y, y^,=x-y\lfloor{a/b}\rfloor\)
- 即\(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;
}
有什么问题可以加qq:1281372141进行交流