欧几里得算法(Euclidean algorithm),是用来求gcd(最大公约数)的算法,它是用较大的数去除较小的数,再用它们的的余数去除除数,再用出现的余数去除之前的余数,如此反复,直到最后余数是0停止。如果是求两个数的最大公约数,那么最后的除数就是这两个数的最大公约数。
代码如下:
int gcd(int a,int b)
{
if(b==0)
{
return a;
}
return gcd(b,a%b);
}
而拓展欧几里得算法,它本身就是用来求ax+by=gcd(a,b)的整数解的.贝祖定理又说明了对任何整数a,b和它们的最大公约数d,若a,b是整数,且gcd(a,b)=d,那么对于任意的整数x,y,ax+by都一定是d的倍数,特别地,一定存在整数x,y,使ax+by=d成立。
推论是:b互质的充要条件是存在整数x,y使ax+by=1.
再看欧几里得定理,最后返回的是a,此时b=0,推到底部的时候,就会有a*1+b*0=gcd(a,b).那么我们就可以递归来计算.又因为根据欧几里得定理可以得到这一步和下一步的原方程分别为:
a*x1+b*y1=gcd;
b*x2+(a%b)y2=gcd;
又因为a%b=a−(a/b)*b,将三个式子联立化简:
x1=y2;
y1=x2-(a/b)*y2;
这就是前一层递归的x,y与后一层的关系,那么我们就可以求出x,y.
int gcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int g=gcd(b,a%b,x,y);
int t=x;
x=y;
y=x-(a/b)*y;
return g;
}
然后根据这个求出来的可以推出来所有的解(过程我就不写了,比较简单).
求同余的解
求同余其实比较简单,只要把同余式子化为拓展欧几里得求的那个线性方程的式子的形式就行.
同余式ax≡c(mod m),可以理解为ax%m=c,令ax/m=b,那么就会存在一个y,使ax-c=by成立,移项,令-y=y,可得到ax+by=c.如果你要用拓展欧拉定理求解,还要满足一个前提,c是gcd(a,b)的倍数.好了,然后直接求出x.依照之前的方法可以求出所有解.
利用拓展欧几里得算法就可以求很多东西,了,例如解方程,求同余式解......
当然,欧几里得算法也可以求逆元.之后会记录在数论专题里,专门腾一篇来写求逆元的方法.