START:
2021-08-07
09:39:32
相关题目链接:
https://www.luogu.com.cn/problem/P1082
https://www.acwing.com/problem/content/879/
介绍:
为了介绍扩展欧几里得,我们先引入一个定理:
贝祖定理:
d=(a,b)代表最大公因数,则设a,b是不全为零的整数,则存在整数x,y,使得ax+by=d
(因为d是a和b的最大公因数,所以ax+by=dk,也就是说ax+by一定是d的倍数,所以存在x,y使得ax+by=d)
贝祖定理其中应用之一:如果ax+by=1有解,那么gcd(a,b)=1
再看一下欧几里得算法:
求a和b的最大公约数:
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
但是对于ax+by=d,我们还得知道式子成立的时候x,y的值是多少,扩展欧几里得算法就是解决这个问题的。
扩展欧几里得算法是递归算法,我们算exgcd(a,b,x,y),就可以递归到exgcd(b,a%b,x,y)的状态,然后更新x,y
我们先写出最后状态的结果,就是exgcd(a,b,x,y)中b==0的时候,我们可以return a;
int exgcd(int a,int b,int &x,int &y){
if(!b){
x=1,y=0;
return a;
}
}
在这里我们写的扩张欧几里得函数,传入的参数有四个,a,b,x,y,其中x,y要使用引用,时刻改变x,y的值,当b==0的时候,我们ax+by=gcd(a,b)====>ax=a,所以x=1,y=0 是其中一个解,所以x=1,y=0。
在b!=0的时候,我们每次都可以递归exgcd(int a,int b,int &x,int &y)
比如exgcd(a,b,x,y),递归到exgcd(b,a%b,x,y)
我们展开其中实现的过程:
exgcd(a,b,x,y)====>exgcd(b,a%b,x,y)
exgcd(a,b,x,y): ax+by=gcd(a,b)=d
exgcd(b,a%b,x1,y1): bx1+(a%b)y1=gcd(b,a%b)=d===>因为a%b=a-(a/b)*b
所以上式等于 ay1+b(x1-[a/b]*y1)=d
我们对比一下前后两个状态的x,y
x=y1
y=x1-(a/b)*y1
所以前后两个状态的x,y关系就清楚了
上代码!!
int exgcd(int a,int b,int &x,int &y){
if(!b){
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,x,y);
int tmp=y;
y=x-a/b*y;
x=tmp;
return d;
}
END:
2021-08-07
10:29:47