欧几里得和扩展欧几里得
Posted happy_code
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了欧几里得和扩展欧几里得相关的知识,希望对你有一定的参考价值。
别人总结的,很详细,http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html
欧几里得算法,就是人们常说的辗转相除法,比较好理解,主要作用是求两个数最大公约数,最小公倍数也可方便的求出
1 int gcd(int a,int b)
2 {
3 return b==0?a:gcd(b,a%b);
4 }
扩展欧几里得就非常神奇了,主要作用是解不定方程, 即 a * x + b * y = c ,我们都知道可以有解,但不是唯一解
用 exgcd 可以很快求出 a * x + b * y = gcd(a,b) 的一个特解。如果 gcd(a,b) | c 即,有整数解,否则无
假如求出特解 x0 ,y0 那么通解 a * x + b * y = gcd(a,b) 为
x = x0 + b / gcd(a,b) * t ( t 为任意整数 )
y = y0 - a / gcd(a,b) * t ( t 同上 )
保证了式子恒等,所以是通解,假如要求 x 的最小非负整数解即 ,设 m = b / gcd(a,b) ,x = (x0 % m + m)%m (前提要 b / gcd(a,b)为正)
再回到 a * x + b * y = c 的特解,设, k = c / gcd (a,b)
那么特解 x1 = k * x0 , y1 = k * x0
式子变为 a * x1 + b * y1 = z ,咋一看通解为 x = x1 + b * t y = x2 - a * t
其实不对,先将两边同除 gcd(a,b) 得 a1 * x1 + b1 * y1 = k
容易看出, a * x + b * y = c 通解为
x = x0*k + b/gcd(a,b) * t
y = y0*k - a/gcd(a,b) * t (t为任意整数)
因为 b1 <= b 所以对 b1 取模一定小于等于 b,
同样方法取最小非负解
扩展欧几里得还可以很方便的求乘法逆元 a * x == 1 (mod m) x 即为 a 的乘法逆元
可以变形为 a * x + m * y == 1 (mod m)
exgcd(a,m,x,y) 后,x 可能是负数,同上方法处理 (x % m/gcd + m/gcd) % m/gcd
1 int exgcd(int a,int b,int &x,int &y) 2 { 3 if (b==0) 4 { 5 x=1; 6 y=0; 7 return a; 8 } 9 int r = gcd(b,a%b,y,x); 10 y-=(a/b)*x; 11 return r; 12 }
以上是关于欧几里得和扩展欧几里得的主要内容,如果未能解决你的问题,请参考以下文章