数论——扩展欧几里得算法

转载自:http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html

说明:

  1. 以下所有除法为向下取整除法,a / b 记为floor(a / b)。
  2. 以下所有涉及运算的数均为整数。
  3. gcd(a, b)表示a与b的最大公约数。
  4. lcm(a, b)表示a与b的最小公倍数。
  5. a % b 表示a / b的余数。
  6. 模运算结果一定为正,如果a % p < 0,让a加上p再模p,即(a + p) % p。
  7. a | b表示a整除b,也就是b % a = 0。
  8. 两个互质数的和(或差)与原来的数仍然是互质数。

欧几里德算法 

简介:

  欧几里德算法又称辗转相除法,用于计算两个整数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 }
View Code

扩展欧几里德算法的主要应用:

  1. 求解不定方程;

  2. 求解模线性方程(线性同余方程);

  3. 求解模的逆元;

求解不定方程:

对于不定整数方程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) 的最小整数解为:(x% 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 }
View Code
原文地址:https://www.cnblogs.com/zaq19970105/p/10768453.html