辗转相除法求最大公约数,相信大家都在高中学过了,它也叫做欧几里得算法。
那么扩展欧几里得算法呢?它也能求出两个数的最大公约数,不过这不是他的目的,他用来解一个线性方程组
这个方程是成立的,这我们不给予证明,只讲他的求法
根据欧几里得定理 gcd(a,b)=gcd(b,a%b),代入上面那个线性方程组有gcd(a,b) = a*x1+b*y1 = gcd(b,a%b) = b*x2+(a%b)*y2
即a*x1+b*y1=b*x2+(a%b)*y2
而a%b = a-a/b*b 这里的a/b是计算机的除法运算 也就是结果向下取整。 比如9%5 = 9-9/5*5 = 9-1*5=4。
代入上式得 a*x1+b*y1=b*x2+(a-a/b*b)*y2 =>a*x1+b*y1 = a*y2+b(x2-a/b*y2)
上面那个等式很重要,因为这建立了x1 y1 x2 y2之间的联系(可以递归求解方程)
这个关系就是 x1 = y2 y1=x2-a/b*y2; //直接看那个红色的的等式
于是等到递归到b = 0的时候(欧几里得计算最大公约数就是当b为0的时候,a为最大公约数)
这时候我们再来看看等式 a*x+b*y = a 这里的b等于0 于是我们可以直接写上一组解(x=1,y=0);
这个时候递归往回走于是解就出来了 ,到这里我们应该可以看懂模板了
int extend_Eulid(int a,int b,int &x,int &y) { if(b == 0) { x = 1;y = 0; return a; } else { ans = extend_Eulid(b,a%b,x,y); int temp = x; x = y; y = temp - a/b*y; return ans; } }
假设我们求出来的一组解为x0,y0 另外一组解为x1,y1;
显然有a*x0+b*y0 = a*x1+b*y1
变形得a(x0-x1) = b(y1-y0)
方程两边同时除以gcd(a,b) 得a'(x0-x1) = b'(y1-y0)
显然这里a'和b'是互素的(因为他们是a,b除以gcd(a,b)得来的)
那么肯定有(x0-x1)是b'的整数倍(因为y1-y0是整数,而a',b'互素嘛)
我们假设x0-x1 = b*k(k为整数) 于是得到x0 = x1+b*k
带入到a(x0-x1) = b(y1-y0) 得a*b*k = b(y1-y0) =>y0 = y1-a*k
附带好资料:http://www.cnblogs.com/ka200812/archive/2011/09/02/2164404.html#2738822