先放一下欧几里得(辗转相除法)求最大公约数
int gcd(int a,int b){
return b == 0 ? a : gcd(b,a % b);
}
学扩展欧几里得之前,先了解一下贝祖定理:
如果a、b是整数,那么一定存在整数x,y使得ax+by=gcd(a,b)。
换句话说In a way,如果ax+by=n有解,那么n一定是gcd(a,b)的若干倍。(可判断一个这样的式子有没有解)
常用 如果ax+by=1有解,那么gcd(a,b)=1
也就是说如果gcd(a,b)!=1 无解…
在gcd的基础上,假设到最后递归到了终点,也就是gcd(b,a%b) a%b=0
a=1, 此时ax+by=1 所以x=1,y=0。
此时递归开始返回,在递归算法中,永远都是先得到下面一个状态的值,我们考虑当前层与下一层的关系
假设这一层 a×x+b×y=gcd(a,b)
那么下一层 b×x1+(a%b)×y1=gcd(b,a%b) 等号右边其实就是1
已知a%b=a-a/b×b 代入
下一层变为 a×y1 + b×(x1 – a/b×y1) = 1
所以x=y1 , y=x1 - a/b×y1
此时此刻,把上面的推导变成代码。
#include<bits/stdc++.h>
#define ll long long
#define T int t;scanf("%d", &t);while(t--)
using namespace std;
int extgcd(int a, int b, int &x, int &y){ //注意x和y要引用
if(b==0){
x=1;
y=0;
return a;
}
int ans=extgcd(b,a%b,x,y);
int temp = y; //临时存y
y=x-a/b*y;
x=temp;
return ans; //返回最大公约数
}
int main(){
int x=0,y=0;
cout<<extgcd(2,3,x,y)<<endl;
cout<<x<<" "<<y<<endl;
return 0;
}