zoukankan      html  css  js  c++  java
  • 数论——扩展欧几里得算法

    转载自: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
  • 相关阅读:
    android截屏
    生产者消费者 ProducerConsumer
    实现RunOnUiThread和RunOnUiThreadBlock
    快速断网恢复方法
    JFrame2
    JFrame
    圆角矩形shader
    [转]Apache commons 工具包应用
    转载 [Java]读取文件方法大全
    转:aop的学习
  • 原文地址:https://www.cnblogs.com/zaq19970105/p/10768453.html
Copyright © 2011-2022 走看看