【墨鳌】【数论小结 01】【乘法逆元】【扩展欧几里得】

数论小结

1. 扩展欧几里得

首先,根据辗转相除法,不难有:

\[\gcd(a,b)=\gcd(b,a\%b) \]

关于扩展欧几里得算法,是解决线性方程:\(ax+by=c\) 当且仅当,\(\gcd(a,b)|c\) 有解

又因为,\(x,y\in\Z\),所以问题可以转化为,解线性方程:\(ax+by=\gcd(a,b)\) 这就是扩展欧几里得算法初始条件

假设,我们有方程的一组解 \(x_0,y_0\), 则:

\[ax_0+by_0=\gcd(a,b)=\gcd(b,a\%b)\qquad(1) \]

于是,构造新的线性方程与其解 \(x_1,y_1\),满足:

\[bx_1+(a\%b)y_1=\gcd(b,a\%b)\qquad(2) \]

联立 \((1),(2)\) 式,我们有:

\[ax_0+by_0=\gcd(a,b)=\gcd(b,a\%b)=bx_1+(a\%b)y_1\\ =bx_1+(a-\lfloor a/b\rfloor\times b)y_1\\ =ay_1+b(x_1-\lfloor a/b\rfloor y_1) \]

结论一:

\[\cases{ x_0\leftarrow y_1\\ y_0\leftarrow x_1-\lfloor a/b\rfloor y_1\\ } \]

结论二:

\[\cases{ x_0\leftarrow y_1\\ y_0\leftarrow x_1\\ a\leftarrow b\\ b\leftarrow a\%b\\ \gcd(a,b)\leftarrow \gcd(b,a\%b)\\ } \]

于是可以考虑设计递归或者迭代代码。

递归版本

    int ex_gcd(int a, int b, int &x, int &y) {
        if (b == 0) {
            x = 1, y = 0;
            return a;
        }
        int d = ex_gcd(b, a % b, y, x);// 注意:这里已经调换了x,y顺序
        y -= (a / b) * x;
        return d;
    }

2. 乘法逆元(扩展欧几里得算法求解)

问题描述

求解 \(ax\equiv1\mod{n}\)

\[ax\equiv1\mod n\\ \iff ax+ny\equiv1\mod n \]

当且仅当,\(\gcd(a,n)=1\) 有解,求解 \(ax+ny=1\) 使用扩展欧几里得算法

乘法逆元-代码

    int inv(int a, int n) {
        int x, y, d = ex_gcd(a, n, x, y);
        if (d == 1) {
            if (x % n <= 0)
                return x % n + n;
            else
                return x % n;
        }
        return -1;
    }
posted @ 2022-04-26 13:53  墨鳌  阅读(52)  评论(0编辑  收藏  举报