扩展欧几里得 基础

先放一下欧几里得(辗转相除法)求最大公约数

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;
} 

猜你喜欢

转载自blog.csdn.net/HHeyanjie/article/details/107451665