转载自:http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html
说明:
- 以下所有除法为向下取整除法,a / b 记为floor(a / b)。
- 以下所有涉及运算的数均为整数。
- gcd(a, b)表示a与b的最大公约数。
- lcm(a, b)表示a与b的最小公倍数。
- a % b 表示a / b的余数。
- 模运算结果一定为正,如果a % p < 0,让a加上p再模p,即(a + p) % p。
- a | b表示a整除b,也就是b % a = 0。
- 两个互质数的和(或差)与原来的数仍然是互质数。
欧几里德算法
简介:
欧几里德算法又称辗转相除法,用于计算两个整数a,b的最大公约数。
描述:
设q = a / b,r = a % b。
a,b,q,r满足a = q*b + r,可得gcd(a, b)=gcd(b, r),即gcd(a, b)=gcd(b, a % b)。
第一种证明:
设d = gcd(a, b),d_ = gcd(b, r)。
由题设可得:d | a,d | b。
∵ r = a - qb。
∴ d | r。
∴ d为 b 与 r 的公约数。
∴ d_ >= d。
同理可得:d >= d_。
∴ d = d_。
∴ gcd(a, b) = gcd(b, r) = gcd(b, a % b)
第二种证明:
设d = gcd(a, b)。
设 m = a / d,n = b / d。
由于d | a,d | b,所以m,n为正整数,且m,n互质。
∵ r = a - qb。
∴ r = (m - qn) * d。
∵ b = n * d。
∵ n,(m - qn)互质。(两个互质数的和(或差)与原来的数仍然是互质数,可用反证法证明)
∴ gcd(b, r) = d。
∴ gcd(a, b) = gcd(b, r) = gcd(b, a % b)
扩展欧几里德算法
描述:
设整数a,b满足a > b >= 0,必然存在整数对x,y,使得gcd(a, b) = a * x + b * y成立。
证明:
设q = a / b,r = a % b。
当b = 0时:
∵ 0除以任何数都等于0,即任何数都可以整除0。
∴ gcd(a, b) = a。
∴ x = 1,y = 0(y可以使任意数,这里取0)。
当b != 0时:
设gcd(a, b) = a * x1 + b * y1,gcd(b, r) = b * x2 + r * y2。
∵ gcd(b, r) = gcd(a, b),r = a - q * b。
∴ a * x1 + b * y1 = b * x2 + (a - q * b) * y2 = a * y2 + b * (x2 - q * y2)
∴ x1 = y2,y1 = x2 - q * y2。
∴ 欲求x1,y1,即求x2,y2,不断递归即可。
代码如下:
1 //ax + by = gcd(a, b) = d 2 // 扩展欧几里德算法 3 inline void ex_gcd(LL a, LL b, LL &x, LL &y, LL &d){ 4 if (!b) {d = a, x = 1, y = 0;} 5 else{ 6 ex_gcd(b, a % b, y, x, d); 7 y -= x * (a / b); 8 } 9 }
扩展欧几里德算法的主要应用:
-
求解不定方程;
-
求解模线性方程(线性同余方程);
-
求解模的逆元;
求解不定方程:
对于不定整数方程a * x + b * y = c,若 gcd(a, b) | c,则该方程存在整数解,否则不存在整数解。
若 gcd(a, b) | c:
设 t = c / gcd(a, b),d = gcd(a, b),则c = d * t。
∵ a * x + b * y = d存在整数解x1,y1。
∴ a * x + b * y = c = d * t必然存在整数解t * x1,t * y1。
若c % gcd(a, b) != 0:
// TODO 知道怎么证明的大佬请丢个链接给我Ozn。
求解模线性方程:
设 d = gcd(a, b)。
同余方程 a * x ≡ c (mod b) 对于未知数 x 有解,当且仅当 d | c。且方程有解时,方程有 d 个解。
求解方程 a * x ≡ c (mod b) 相当于求解方程 a * x + b * y = c, (x, y为整数)。
对 a * x + b * y = c 两边模b可得:a * x ≡ c (mod b)。
对于方程为什么有解,上面已经讨论过了,以下讨论方程为什么有 d 个解。
设 t = c / d,s = b / d。
设 a * x + b * y = d的整数解为xd,yd。
设 a * x + b * y = c的一组整数解为x0,y0。
令 x0 = t * xd,y0 = t * yd。
则方程 a * x ≡ c (mod b) 的第 i 个解为:xi = (x0 + i * s) % b,(0 <= i < d)。
且方程 a * x ≡ c (mod b) 的最小整数解为:(x0 % s + s) % s。
证明:
先证明解的最小公差 s = b / d:
∵ a * x0 ≡ c (mod b),a * (x0 + s) ≡ c (mod b)。
∴ a * s ≡ c (mod b)。
∴ a | (a * s),b | (a * s)。
∴ (a * s) 为 a,b 的公倍数。
∴ (a * s)min = lcm(a, b) = a * b / d。
∴ smin = b / d。
再证明有d个解(此处的解是指小于b的解,不然解有无数个):
∵ (a * xi) % b = (a * (x0 + i * s)) % b = (a * x0 + a * i * b / d)) % b。
∵ d | a 且 d | b。
∴ (a * xi) % b = (a * x0 + b * i * a / d)) % b。
∴ (a * xi) % b = (a * x0) % b。
∵ a * x0 ≡ c (mod b)
∴ a * xi ≡ c (mod b)
∵ xi+d = (x0 + i * s + d * s) % b = (x0 + i * s) % b = xi。
∴ 解有 d 个。
求模的逆元:
对于方程 a * x + b * y = 1,也就是gcd(a, b) = 1的时候(a,b互质)。
所求解的x就是a关于b的逆元。
所求解的y就是b关于a的逆元。
证明:
a * x + b * y = 1 两边模b得:a * x ≡ 1 (mod b)。
即 x ≡ inv(a) (mod b)。
代码如下:
1 // 求a关于p的逆元,如果不存在,返回-1 2 // a与p互质,逆元才存在 3 inline LL inv_mod(LL a, LL p){ 4 LL d, x, y; 5 ex_gcd(a, p, x, y, d); 6 return d == 1 ? (x % p + p) % p : -1; 7 }