一、欧几里得算法
对于两个正整数a,b,若要求他们的最大公约数,从2开始遍历到b(假设a>b)的时间复杂度是O(n),但用欧几里得算法可以将其复杂度降为O(logn)。
文字描述:欧几里得算法也称辗转相除法,即用较大的数对较小的数取余数,余数记作t。若余数t不为零,则继续用b对t取余直到取得余数为0为止(递归出口)。为零时,形参a所代表的数就是二者的最大公约数。
代码如下:
int gcd(int a,int b)
{
if(b == 0)
{
return a;
}
return gcd(b,a%b);
}
二、拓展欧几里得算法
一定存有整数x,y,使a*x+b*y=gcd(a,b)
设a*x1+b*y1=gcd(a,b);----①
根据欧几里得算法我们可以得知:gcd(a,b)=gcd(b,a%b);----②
gcd(b,a%b)=b*x2+(a%b)*y2;----③
对于a%b我们可以将其转换成数学计算符号a-b*(b/a),这里的b/a在数学中是向下取整,但在编程中由于整数类型除法的特性,便可不做特殊处理。
联立上三式可以得出:a*(x1-y2)=b*(x2-y1-b*(b/a)),由于a,b是随机的,所以两边若相等必须括号内为0,即x1=y2,y1=x1-(a / b)*y1。
我们可以用递归的方法求出x,y。递归的出口是b=0,即x=1,y=0,我们直接赋值就可以了。
代码如下:
int exGod(int a,int b,int &x,int &y){
if(b==0){
x=1;
y=0;
return a;
}
int g=exGod(b,a%b,x,y);
int temp=x;
x=y;
y=temp-a/b*y;
return g;
}