欧几里得也就是我们说的辗转相除法,用于求最大公约束(辗转相减法也可以求)。
欧几里得
int gcd(int a,int b)
{
if(b==0) return a;
else return gcd(b,a%b);
}
这是递归的代码,下面来证明
设c==gcd(a,b); r=a%b;
则 a==x1*c; b==x2*c; r==a-x3*b; (x1,x2,x3均为正整数)
将a,b代入得:r==x1*c-x3*x2*c==(x1-x3*x2)*c;
因此a,b的余数r是gcd(a,b)的倍数;
因此可以得到:c==gcd(b,r); 从而得到gcd(a,b)==gcd(b,r);
所以当循环一直进行下去直到r==0,所求的数即gcd(a,b);
欧几里得及其扩展
我们知道,对于自然界的正整数...a,b...一定满足ax+by==gcd(a,b); (解一定存在,根据数论中的相关定理)
(1)...ax+by==gcd(a,b);
(2)...bx1+a%by1==gcd(b,a%b); (运用欧几里算法)
(3)...gcd(a,b)==gcd(b,a%b); (欧几里得算法)
(4)...ax+by==bx1+a%b*y1; (在计算机里a%b==(a-a/b*b))
(5)...ax+by==bx1+ay1-a/b*by1;
(6)...ax+by==ay1+b(x1-a/b)y1; (合并同类项)
(7)...x=y1,y=x1-a/b*y1; (结论)
所以我们知道x,y和方程的下一个状态量(x1,y1)有关,而方程最后一个状态(即gcd(a,b)终点,b==0;)此时:
ax+0==a; (gcd(a,b)的最终返回值为a) 可以得到一组解{x==1; y==0},根据此解层层上推即可得到最开始的x,y.
struct Euclid
{
int x,y,gcd;
}AC;//全局变量;
int exgcd(int a,int b)
{
if(b==0)
{
AC.x=1;
AC.y=0;
return a;
}
int ret=exgcd(b,a%b);
int t=AC.x;
AC.x=AC.y;
AC.y=t-a/b*AC.y;
return ret;
}