拓展欧几里得

拓展欧几里得

在拓展欧几里得定理之前,先介绍以下贝祖定理

如果方程式 \(ax + by = m\) 成立,那么 \(gcd(a, b) | m\)

显然,我们可以把原方程式写作:\(m = k1 *g * x + k2 * g * y = g(k1 * x + k2 * y)\)

根据贝祖定理,如果有 \(ax + by = 1\) ,那么 \(gcd(a, b) = 1\), 即 \(a\)\(b\) 互质。

我们可以使用著名的辗转相除法算出来 \(gcd(a, v=b)\) :

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

拓展欧几里得

给出 \(ax + by = m\) ,如何求出他的一组解?

根据贝祖定理,只要我们求出 \(ax + by = gcd(a, b)\) 即可,由于 \(gcd(a, b) | m\) ,所以可以求出原式的一组因子,只需要乘上 \(m / gcd(a, b)\) 即为原式的一组解。

那么问题就转化为了,求 \(ax + by = gcd(a, b)\) 的一组 \((a, b)\)

\(gcd(a, b)\) 可以用欧几里得辗转相除求出,而 \(a, b\) 可以在求的过程中得出。

假设我们到达了终点,此时 \(a = gcd(a, b), b = 0\) ,那么有 \(x = 1, y = 0\)

由于\(gcd(a, b)\) 是递归的,当我们想要求得 \(ax + by = m\) 时,我们已经求出了 \(bx + (a \% b)y = m\) 的一组解。

\(a \% b = a - \lfloor \dfrac a b \rfloor * b\)

把已有的式子化作:\(bx + (a - \lfloor \dfrac a b \rfloor * b)y = m\)

那么,可以得到:\(ay + b(x - \lfloor \dfrac a b \rfloor * y) = m\)

所以我们发现,如果从上一层状态推下来,那么:\(x = y, y = x - \lfloor \dfrac a b \rfloor * y\)

Code

int exgcd (int a, int b, int & x, int & y)
{
    if (!b) return x = 1, y = 0, a;
    int r = exgcd(b, a % b, x, y);
    tie(x, y) = make_tuple(y, x - (a / b) * y);
    return r;
}

由于 \(ax + by \equiv m \pmod p\) 有无穷多组,而我们只计算出了一种,那么如何得到其他解?

假设我们得到解为 \(x_0, y_0\) ,还有另外一组解为 \(x_1, y_1\) ,那么可以得到:

\(ax_0 + by_0 \equiv m \pmod p\)

\(ax_1 + by_1 \equiv m \pmod p\)

两个柿子相减,得到 \(a(x_0 - x_1) \equiv -b(y_0 - y_1) \pmod p\)

两边同时除以 \(gcd(a, b)\) ,有 \(a / gcd(a, b) (x_0 - x_1) \equiv -b / gcd(a, b)(y_0 - y_1) \pmod p\)

此时 \(a / gcd\)\(b / gcd\) 互质,所以一定有 \(a / gcd(a, b) | (y_0 - y_1), b / gcd(a, b) | (x_0 - x_1)\)

我们记 \(x_1 = x_0 + k * \dfrac{b}{gcd(a, b)}\) ,同理 \(y_1 = y_0 + k * \dfrac{a}{gcd(a, b)}\)

欧几里得用途

求逆元

\(a * a^{-1} \equiv 1 \pmod p\) ,可以写成 \(a * a^{-1} \equiv kp + 1 \pmod p\)

这样,我们就可以得到柿子 : \(a * a^{-1} + kp \equiv 1 \pmod p\)

这就是拓展欧几里得公式,由于 \(a, p\) 都已知,只需要用拓展欧几里得算出 \((a^{-1}, k)\) 即可。

注意拓展欧几里得可以计算 \(p\)\(a\) 非互质情况下的逆元,而欧拉定理不能算出。

posted @ 2021-11-20 13:52  Horb7  阅读(51)  评论(0编辑  收藏  举报