1、欧几里德 – 求解最大公约数
gcd(a,b) = gcd(bn+r, b) = gcd(a%b, b) = gcd(b, a%b) 假定 a>b; a=bn+r;
int gcd(int a, int b){
return b ? gcd(b, a%b) : a;
}
int gcd(int a , int b)
{
int r;
while(b!=0)
{
r = a; a = b; b = r%b;
}
return a;
}
即使a<b 上面代码也没问题,经过第一次调用a, b会对调的
2\ 扩展欧几里德 – 求解方程 ax+by = gcd(a, b);
基本算法:对于不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数,必然存在整数对 x,y ,使得 gcd(a,b)=ax+by。
扩展欧几里德算法的应用主要有以下三方面:
(1)求解不定方程;
(2)求解模线性方程(线性同余方程);
(3)求解模的逆元;
假定 a>b
gcd(a, b) = a*x + b*y;
gcd(b, a%b ) = b*x1 + (a%b ) *y1 = b*x1 + (a- a/b *b )*y1;
gcd(a, b ) = gcd(b, a%b);
求解
b==0
gcd(a,b) = a = a*x + b*y; ==> x=1; y=0;
b!=0
a*x + b*y = b*x1 + (a-a/b * b) * y1 = a*y1 + b *(X-a/b*y1);
==> x = y1 = … ;
==> y = x1-a/b*y1 = …;
通过不断迭代就能求解x, y
// 扩展的欧几里德-递归算法
int exgcd(int a, int b, int *x, int *y)
{
if ( b == 0)
{
*x=1;
*y=0;
return a;
}
// 先求出内部x, y
int r = exgcd(b, a%b, y, x);
// 更新外部x , y
*y -= a/b * (*x);
}
1、递推公式
根据下图 a=1398 b=324 商q=a/b 余数r=a%b
gcd(a, b) = gcd(b, r1=a%b) = gcd(r1, r2=b%r1) = gcd(r2, r3=r1%r2)
每一个 r 都可以转换用a, b 标示
假定 r1 = a*x1+b*y1; r2=a*x2+b*y2;
r3 = a*x3 + b*y3 = r1 % r2 = (a * x1 + b y1) - r1/r2 ( a*x2 + b *y2)
= a(x1- r1/r2 * x2) + b(x2 - r1/r2 * y2);
==> r3 = r1 % r2;
==> x3 = x1- r1/r2 * x2
==> y3 = x2 - r1/r2 * y2
也就是说 有了x1 y1 r1 x2 y2 r2 就能推动上面的等式
当 r3 = r1 % r2 = 0时 结束, 此时 r2 = gcd(a, b) = gcd(r2, 0) = a*x2+b*y2; 此时 x2, y2, r2 即为所求
2、初始值
令x1=1 , y1=0; r1=a*1 + b*0 = a =;
令x2=0, y2=1; r2=a*0 + b*1 = b = b%a ; (b<\a ==> b=b%a)
x1\x2\y1\y2不能随便取值 要满足
因为 gcd(a, b) = gcd(b, r1=a%b) = gcd(r1, r2=b%r1)
所以要满足 (a*x2+b*y2) = b % (a*x1+b*y1)
令x2=0; y2=1; 那么只要满足 a*x1 + b*y1 > b 都可以 eg x1=1;x2=1;r1=a+b; …
// 扩展的欧几里德-非递归算法
int exgcd(a, b)
{
int x1, y1, r1, x2, y2, r2, x3, y3, r3;
x1=1; y1=0; r1=a;
x2=0; y2=1; r2=b;
while( r1%r2 )
{
r3 = r1%r2;
x3 = x1 - r1/r2 * x2;
y3 = y1 - r1/r2 * y2;
// 交换
x1=x2;y1=y2;r1=r2;
x2=x3;y2=y3;r2=r3;
}
printf("%d=%d*%d+%d*%d\n",r2, a, x2, b, y2);
return 0;
}
有关链接
http://anh.cs.luc.edu/331/notes/xgcd.pdf
http://math.cmu.edu/~bkell/21110-2010s/extended-euclidean.html
http://blog.csdn.net/yoer77/article/details/69568676