欧几里德算法gcd
概述
该算法即经典算法辗转相除法,假设a,b(a>b)的最大公约数为gcd(a,b),辗转相除法的内容就是:gcd(a,b)=gcd(b,a%b)(边界gcd(k,0)=k)。
证明
(看完百度百科后写的=_=,非常像,百度百科原版证明可以见此链接http://baike.baidu.com/view/255668.htm)
设c=gcd(a,b),a=mc,b=nc,r=a%b,则可设r=a-kb
∴r=a-kb=mc-kb=mc-knc=(m-kn)c
∴r是c的因数
∵n与m-kn互质(假设n与m-kn不互质,则可设m-kn=xd,n=yd(d>1),那么m=xd+kn=xd+kyd=(x+ky)d,n=yd,则a=(x+ky)cd,b=ycd,那么a,b的一个公共因子就是cd,而cd>c,与题设不符,所以n与m-kn互质)
∴gcd(b,r)=c
∴gcd(a,b)=gcd(b,r)
特殊:当r=0时,显然b是a的因子,gcd(a,b)=gcd(b,0)=b,正确。
ps:当a<=b时,此公式仍然适用,请读者独立思考~
代码
int gcd(int a,int b) {if (b) return gcd(b,a%b); else return a;}
效率
不难得出,每次a至少/2(或者a,b交换),所以效率为log2(a)
ps:处理次数最多的是斐波那契数列的相邻两个,因为斐波那契数列相邻两个数f[i-1],f[i]每次处理过后变成了f[i-2],f[i-1]。
扩展欧几里德算法exgcd
概述
对于一个方程ax+by=(a,b)(gcd(a,b)可简写为(a,b),a>b),求任意一组x,y。扩展欧几里得算法可以快速求解x和y。
方法
首先我们知道gcd(a,0)=a,此时x=1,y可以为任何数(一般给0)。根据欧几里得算法,我们可以得到:
bX+(a%b)Y=(b,a%b)=(a,b)(假设X和Y已经求出了)
联立一下:ax+by=bX+(a%b)Y
因为a%b=a-b*(a div b)(注:div表示整除以,也就是编程中的)
所以ax+by=bX+aY-b*(a div b)*Y
移项,可得a(x-Y)=b(X-y-(a div b)*Y)
那么只要两边=0,就可以得到一组解:
x-Y=0
X-y-(a div b)*b*Y=0
即x=Y,y=X-(a div b)*Y
那么只要递归处理就行了。
ps:不难发现,得到一组解x0,y0之后,可以推出所有解:
x=x0+k*b/(a,b)
y=y0-k*a/(a,b)
k∈Z
代码
int exgcd(int a,int b,int &x,int &y)
{
if (!b) {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;
}
效率
和gcd效率一样。
运用
有了扩展欧几里得算法,就可以快速求解乘法逆元和模方程了。