先看欧几里得算法 即辗转相除法
gcd(a, b) = gcd(b, a % b);
简单的证明
证明: 令a % b = r 设 d 是 a,b 的公约数 即 d|a && d|b 又 r = a – kb 所以 r|d 即a,b的公约数都是 b,r的公约数 设 d’ 是 b, r 的公约数 即 d’|b && d’|r 又 a = kb + r 所以d’|a 即 b,r的公约数都是 a,b的公约数 所以gcd(a,b) = gcd(b, a%b);欧几里得算法的递归代码
int gcd(int a, int b) { return (b ? gcd(b, a % b) : a); }
对于二整数a b 必存在整数 x y 使得 ax+ by = gcd(a, b) 可以通过扩展欧几里得算法求出一组满足的x y
设<span style="white-space:pre"> </span>a*x1 + b*y1 = gcd(a, b)<span style="white-space:pre"> </span>(1) <span style="white-space:pre"> </span>b*x2 + a%b * y2 = gcd(b, a%b)<span style="white-space:pre"> </span>(2) 又 gcd(a,b) = gcd(b,a%b) 所以有 a*x1 + b*y1 = b*x2 + (a-a/b*b)*y2 此处的’/’为向下取整除 化简有 a*x1 + b*y1 = a*y2 +b* (x2 – a/b*y2) 那么有 x1 = y2, y1 = x2 – a/b*y2; 所以我们可以通过方程(2)的一组解得到方程(1)的一组解 这样递归下去 类似辗转相除法 可以发现最后总可以递归到 方程 a*x + 0*y = gcd(a, 0) (3) 而方程(3)的一组解为 x = 1, y = 0 那么我们在递归求gcd(a,b)的过程中 就可以一起求出方程a*x + b*y = gcd(a, b)的一组解扩展欧几里得的递归代码
ll exGcd(ll a, ll b, ll &x, ll &y) { if(!b) { x = 1, y = 0; return a; } ll r = exGcd(b, a % b, x, y), t = y; y = x - a / b * y; x = t; return r; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/acvay/article/details/46848769