写在前面:
本文参考了 leader_one 的文章
欧几里得算法(gcd):
介绍:
欧几里得算法(也称辗转相除法)是目前已知求最大公约数的最快通用算法,具有代码复杂度低、易理解、用途广等诸多优点,用于求a,b的最大公约数。
算法实现:复杂度O(log n)
while(b!=0)
{
r = a % b;
a = b;
b = r;
}
最终的a即为原a,b最大公约数
扩展欧几里得算法(exgcd):
介绍:
1.这个算法用来干什么呢?
首先引入一个引理:对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然
存在整数对 x,y ,使得 gcd(a,b)=ax+by。
gcd(a,b)=ax+by这个等式被称为:贝祖等式。
而exgcd就是用来求整数对x,y的一组解的。
进一步继续想 既然一组解满足 gcd(a,b)=ax+by,那么若将x,y同时扩大k倍,kax+kby=kgcd(a,b),不妨设 kgcd(a,b)=z。
那么现在exgcd作用就是可以求解 z=ax+by。(z=k*gcd(a,b) z为整数)。
2.怎么实现这个算法:
求z=ax+by 求要先求 ax+by=gcd(a,b)。求出来后只需要 x’=xk y’=yk 就求得了原式的解
那么接下来先求 ax+by=gcd(a,b)
只讨论a>b的情况即可,若b>a ,swap(a,b)即可,同时解出来的x是y ,y是x。
证明:
当b=0 时,gcd(a,0)=a=ax+by。 所以 x=1 y=0。
exgcd(a,b) =ax1+by1
exgcd(b,a mod b) =bx2+(a mod b)x2
exgcd(a,b)=exgcd(b,a mod b) [ 这个就是辗转相除法(gcd)的第一步]
ax1+by1=bx2+(a mod b)x2
ax1+by1=bx2+(a-[a/b]*b)x2 — 注:[ ]为取整符号
ax1+by1=ay2+b(x2-[a/b]*y2)
所以: x1=x2 y1=x2-[a/b]*y2
这样就可以解出来一组解了
代码实现:
int exGcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x = 1;
y = 0;
return a;
}
int r = exGcd(b,a%b,x,y);
t = x; x = y;
y = t-a/b*y;
return r;
}