欧几里的算法:
欧几里的算法又叫辗转相除法, 可以求解两数之间的最大公约数,当然最大公约数求出来了
也可得最小公倍数。
求 a 和 b 的最大公约数:
假设有 x 满足 a = b * x + c;
假设有a 和 b 的最大公约数是 k , 那么满足 k | b , 就满足 k | (b * x) , 因为 k | a ,所以就有 k | (a - b*x)
因为 c=a-b*x,即是k |c; 所以求 a 和 b, 之间的最大公约数的问题就转化成了 ,求 b 和 c 之间的最大公约数
的问题。 即gcd( a, b) = gcd (b, a mod b) 依次类推,当最后的 a= b*x+c ,c=0 时,即a%b=0,即gcd(a,b)=b
那么最原始的a 和b 的最大公约数就是目前的 b.
int gcd(int a,int b)
{
if(a%b==0)
return b;
return (b,a%b);
}
扩展欧几里得算法:
通常使用扩展欧几里得算法求解模线性方程。 a * x= b (mod n)
转化为 a*x + b*y = z ,其中已知 a,b,z 可求 x, y 的值。
扩展欧几里得就是采用倒退的形式求 x, y 的值的(以下讨论a>b)
显然当 b=0,gcd(a,b)= a。此时 x=1,y=0;
当a>b>0 时
设 a * x1+ b * y1= gcd(a,b);
b* x2 + (a mod b)* y2= gcd(b,a mod b);
根据欧几里德原理有 gcd(a,b) = gcd(b,a mod b);
则:a * x1+ b * y1= b * x2+(a mod b)* y2;
即:a * x1+ b * y1= b * x2+ (a - [a / b] * b)* y2 = a * y2+ b * x2- [a / b] * by2;(a mod b = a - [a / b]*b;
[a / b]代表a整除b) 也就是a * x1+ b * y1 = a * y2 + b *(x2- [a / b] *y2;
根据恒等定理得:x1=y2;y1=x2- [a / b] *y2;
这样我们就得到了求解 x1,y1 的方法:x1,y1 的值基于 x2,y2
由引理我们知道:ax+by = z,z为gcd(a,b)若干倍,所以我们先求解ax+by = gcd(a,b),再将求
出的解乘以 z/gcd(a,b)就好了。
依旧递归实现,因为上一次的x,y与下一次的x,y的值有关,所以我们从x=1,y=0(此时b=0)的情况开始递归上来
int exgcd(int a,int b,int &x,int &y)
{
if(b==0){
x=1;
y=0;
return a;
}
int u=exgcd(b,a%b,x,y);
int temp=x;
x=y;
y=temp-(a/b)*y;
return u;
}