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

    欧几里得算法基于这样一个 GCD 递归定理:

    $gcd(a, b) = gcd(b, amod{b}) $

    证明如下:

    假设 $a > b$, $a = kb + r(0 <= r < b)$, 即 $amod{b} = r$.

    若有 $d mid a$ 且 $d mid b$, 必然有 $d mid a - kb$, 即 $d mid r$. 由此得知, $a$ 与 $b$ 的所有公约数必然是 $b$ 与 $r$ 的公约数.

    若有 $d mid r$ 且 $d mid b$, 必然有 $d mid kb + r$, 即 $d mid a$. 由此得知, $b$ 与 $r$ 的所有公约数必然是 $a$ 与 $b$ 的公约数.

    所以 $gcd(a, b) = gcd(b, r)$, 即 $gcd(a, b) = gcd(b, amod{b})$

    然后, 通过不断递归直到 $b = 0$, 再不断返回就能求出 $gcd(a, b)$.

    int gcd(int a, int b) {
        return b ? gcd(b, a % b) : a;
    }

    扩展欧几里得算法利用了欧几里得算法的一些有用信息, 从而求出同余模方程 $ax + by = gcd(a, b)$ 的一组解. 通过数学归纳法可以证明扩展欧几里得算法的正确性.

    1. 当 $b = 0$ 时, $gcd(a, b) = a$, 显然 $x = 1, y = 0$ 是一组合法的解

    2. 当 $b > 0$ 时, 假设我们已经求得了方程 $bx + (amod{b})y = gcd(b, amod{b})$ 的一组解 $(x_0, y_0$), 同时设 $(x_1, y_1)$ 是方程 $ax + by = gcd(a, b)$ 的一组解, 那么有

    $ax_1 + by_1 = bx_0 + (amod{b})y_0$

    $ax_1 + by_1 = bx_1 + (a - frac{a}{b}cdot b)y_1$

    $ax_1 + by_1 = b(x_0-frac{a}{b}cdot y_0) + ay_0$

    对应相等, 我们可以得到

    $x_1 = y_0$

    $y_1 = x_0 - frac{a}{b}cdot y_0$

    void exgcd(int a, int b, int &d, int &x, int &y) {
        if (!b) {
            d = a;
            x = 1;
            y = 0;
        } else {
            exgcd(b, a % b, d, y, x);
            y -= (a / b) * x;
        }
    }

    (上述代码运用了一点小技巧: 让 $x$ 与 $y$ 在递归调用时错位以减少代码量, 整理一下对应关系就能发现其正确性.)

    运用欧几里得算法得到方程 $ax + by = gcd(a, b)$ 的一组解 $(x_1, y_1)$ 后, 假设该方程的另一组解为 $(x_2, y_2)$, 那么有

    $ax_1 + by_1 = ax_2 + by_2$

    整理得

    $a(x_1-x_2) = b(y_2-y_1)$

    两边同除以 $g=gcd(a, b)$, 得

    $a'(x_1-x_2) = b'(y_2-y_1)$

    因为 $a'$ 与 $b'$ 互质, 所以 $b' mid (x_1-x_2)$, 则可设 $x_1-x_2 = kb'$, 那么有

    $a'k = y_2-y_1$

    即 $y_2 = y_1+ka'$

    同时也得到了 $x_2 = x_1+kb'$

    由上, 得到一组解 $(x_1, y_1)$ 后, 就得到另一组解 $x_2 = x_1+kb', y_2 = y_1+ka'$.

    由扩展欧几里得算法, 我们就可以解出一般的不定方程 $ax + by = c$ 的解:

    若 $gcd(a, b)  mid  c$ , 则方程有解. 假设 $(x_0, y_0)$ 是方程 $ax + by = gcd(a, b)$ 的一组解, 那么我们可以得到方程 $ax + by = c$ 的一组解 $(frac{c}{gcd(a,b)}cdot{x_0}, frac{c}{gcd(a,b)}cdot{y_0})$;

    否则, 方程无整数解.

    另外, 我们还可以用扩展欧几里得算法来解线性同余模方程组. 比如:

    $xequiv m_1pmod{a_1}$

    $xequiv m_2pmod{a_2}$

    ...

    $xequiv m_npmod{a_n}$

    我们可以将其两两合并. 比如对于前两个方程, 假设 $m_1y+a_1=x$, $m_2z+a_2=x$, 则

    $m_1y-m_2z=a_2-a_1$

    这是一个一般的不定方程, 用扩展欧几里得算法得到一个 $y_0$ 值, 我们就可以计算出一个可行的 $x_0$ 值, 那么显然 x 的一般解就是

    $x = x_0 + t[m_1, m_2]$

    由这个等式我们又可以构造出一个新的方程:

    $xequiv x_0pmod{[m_1, m_2]}$

    再将这个方程与第三个方程联立, 得到新的方程. 重复此过程即可得到该方程组的一个解.

  • 相关阅读:
    POJ1125-Stockbroker Grapevine【Floyd】(模板题)
    Codeforces 862B (二分图染色)
    hdu3047 Zjnu Stadium【带权并查集】
    HDU1532 网络流最大流【EK算法】(模板题)
    hdu 2063 过山车【匈牙利算法】(经典)
    HDU-2066-一个人的旅行 【Dijkstra】
    HDU 3625 Examining the Rooms【第一类斯特灵数】
    HDU4372-Count the Buildings【第一类Stirling数】+【组合数】
    HDU 6114 Chess【逆元+组合数】(组合数模板题)
    HDU1211 密文解锁 【扩展欧几里得】【逆元】
  • 原文地址:https://www.cnblogs.com/lsdsjy/p/gcd.html
Copyright © 2011-2022 走看看