版权声明:此文为作者原创,若觉得写得好请点个赞再离开。当然,也欢迎在讨论区指出本文的不足,作者会及时加以改正。转载请注明地址: https://blog.csdn.net/chenxiaoran666/article/details/83448173
前言
扩展欧几里得算法是一个很好的解决同余问题的算法,非常实用。
欧几里得算法
简介
欧几里得算法,又称辗转相除法。
主要用途
求最大公因数
gcd。
公式
gcd(a,b)=gcd(b,a%b)
公式证明
a可以表示成
a=kb+a%b(
k为自然数)。
假设
g是
a,b的一个公约数,则有
g∣a,g∣b。
∵a%b=a−kb,
∴g∣(a%b),∴g是
b,a%b的公约数。
综上所述,
a,b和
b,a%b的公约数是一样的,其
gcd也必然相等。
代码实现
inline int gcd(int x,int y) {return y?gcd(y,x%y):x;}
扩展欧几里得算法
简介
扩展欧几里得建立于欧几里得算法的基础上。(该算法的升级版 徐xgcd有待XuRuiYang奆佬发明)
主要用途
对于已知a,b求解x,y使其满足ax+by=gcd(a,b)。
解法
我们可以对
(a,b)不断辗转相除。
根据欧几里得算法,最后剩下的两个数一定为
(gcd(a,b),0),
显然,此时
x=1,y=0是原式的一组解。
现在,我们需要考虑,若已知
(b,a%b)的解,如何推出
(a,b)的解。
设
x0,y0为
(b,a%b)的一组解,则
x0⋅b+y0(a%b)=gcd(b,a%b)。
将这个式子转化一下,可以得到
x0⋅b+y0(a−⌊ba⌋∗b)=gcd(a,b)。
去括号,得
x0⋅b+y0⋅a−(y0⋅⌊ba⌋)⋅b=gcd(a,b)。
合并同类项,得
y0⋅a+(x0−y0⋅⌊ba⌋)⋅b=gcd(a,b)。
∴x=y0,y=x0−y0⋅⌊ba⌋是原式的一组解。
递归即可。
代码实现
inline int exgcd(int x,int y,int &s1,int &s2)
{
if(!y) return s1=1,s2=0,x;
register int res=exgcd(y,x%y,s2,s1);
return s2-=x/y*s1,res;
}
扩欧的典型应用:求乘法逆元
Link
乘法逆元 详见博客 浅谈乘法逆元的三种解法