数论——线性同余方程、乘法逆元 学习笔记

这篇具有很好参考价值的文章主要介绍了数论——线性同余方程、乘法逆元 学习笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

数论——线性同余方程、乘法逆元

众所周知:

数论——线性同余方程、乘法逆元 学习笔记

说明

如果爆 int 请自行开 long long 或边读边模,或高精度处理。

同余

定义

\(a \bmod m = b \bmod m\),则称 \(a\)\(b\) 关于模 \(m\) 同余,记为 \(a \equiv b \pmod m\).

同余的性质

  1. 反身性:\(a \equiv a \pmod m\)
  2. 对称性:若 \(a \equiv b \pmod m\),则 \(b \equiv a \pmod m\)
  3. 传递性:若 \(a \equiv b \pmod m\)\(b \equiv c \pmod m\),则 \(a \equiv c \pmod m\)
  4. 同余式相加:若 \(a \equiv b \pmod m\)\(c \equiv d \pmod m\),则 \(a \pm c \equiv b \pm d \pmod m\)
  5. 同余式相乘:若 \(a \equiv b \pmod m\)\(c \equiv d \pmod m\),则 \(a \times c \equiv b \times d \pmod m\)
  6. 乘方:若 \(a \equiv b \pmod m\),则 \(a^k \equiv b^k \pmod m\)
  7. 除法1:若 \(ka \equiv kb \pmod{km}\),则 \(a \equiv b \pmod m\)
  8. 除法2:若 \(ka \equiv kb \pmod m\),则 \(a \equiv b \pmod{m / \gcd(k, m)}\)

线性同余方程

形式

关于 \(x\) 的方程,形如 \(ax \equiv n \pmod b\),则称之为线性同余方程(Linear Congruence Equation)。

一般要求求出特解,或 \(x \in [0, b - 1]\) 的通解。

求解方法

方程 \(ax \equiv n \pmod b\) 可以理解为 \(ax + by = n\),其中 \(y\) 为一个整数。

  • 证明如下:

    因为 \(ax + by = n\)
    所以 \((ax + by) \bmod b = n \bmod b\)

    \(ax \bmod b + by \bmod b = n \bmod b\)
    因为 \(by \bmod b = 0\)

    所以 \(ax \bmod b = n \bmod b\)
    转换为同余方程的形式就是 \(ax \equiv n \pmod b\).

因此原方程转化为 \(ax + by = n\),接下来就是扩展欧几里得算法的事情了;
详见:https://www.cnblogs.com/RainPPR/p/gcd-bezouts-exgcd.html

解的判断

扩展欧几里得算法只能求解 \(ax + by = \gcd(a, b)\) 的情况,
所以只有当 \(n = k \times \gcd(a, b)\)\(k \in \mathbb{Z}^+\),才可以用扩展欧几里得算法求解。

  • 证明如下:

    可以求出一组 \(x_0\)\(y_0\),使得 \(ax_0 + by_0 = \gcd(a, b)\)
    等式两边同时乘以 \(k\),便得到:\(akx_0 + bky_0 = k \times \gcd(a, b)\)

    因此可得到 \(\left\{\begin{matrix} x = kx_0 \\ y = ky_0\end{matrix}\right.\)

    此时便有 \(ax + by = n\).

特解到通解

下面假设有解:
我们已经将 \(ax \equiv n \pmod b\) 转化为 \(ax + by = n\),并通过扩展欧几里得算法解出来一个通解 \(x_0\).

然后请看:https://www.cnblogs.com/RainPPR/p/gcd-bezouts-exgcd.html

\(t = \dfrac{\operatorname{lcm}(a, b)}{a}\),则有通解 \(x = x_0 + kt\),其中 \(k \in \mathbb{Z}\)

特殊化的线性同余方程

考虑方程 \(ax \equiv 1 \pmod b\),也就是上面的 \(n = 1\)

此时存在解的条件为 \(k \times \gcd(a, b) = n = 1\),也就是 \(k = 1\) 时的情况:
\(\gcd(a, b) = 1\),即 \(a\)\(b\) 互质,这样就可以用扩展欧几里得算法求解 \(ax + by = 1\) 了。

所以此时的通解公式也可以化简为 \(x = x_0 + kb\)

证明:\(t = \dfrac{\operatorname{lcm}(a, b)}{a}\),而 \(\operatorname{lcm}(a, b) = ab\),所以就有 \(t = b\)

代码实现

// ax = 1 (mod b)
int lieu1(int a, int b)
{
    int x, y;
    int d = exgcd(a, b, x, y);
    if (d != 1)
        return -1;
    return (x % b + b) % b;
}
// ax = n (mod b)
int lieu(int a, int b, int n)
{
    int x, y;
    int d = exgcd(a, b, x, y);
    if (n % d != 0)
        return -1;
    int t = b / d;
    return (x % t + t) % t;
}

乘法逆元

有理数取模

加减法:\((a \pm b) \bmod p = (a \bmod p \pm b \bmod p) \bmod p\).

乘法:\((a \times b) \bmod p = (a \bmod p \times b \bmod p) \bmod p\).

那除法呢?举例可知 \(\dfrac{a}{b} \bmod p\) 不一定等于 \(\dfrac{a \bmod p}{b \bmod p}\).

\(\dfrac{10}{2} \bmod 3 = 5 \bmod 3 = 2\),而 \(\dfrac{10 \bmod 3}{2 \bmod 3} = \dfrac{1}{2}\).

乘法逆元的定义

\(\dfrac{a}{b} \bmod p = (a \times x) \bmod p\)

则称 \(x\)\(b\) 的模 \(p\) 意义下的乘法逆元(或 \(x\)\(b \bmod p\) 的逆元),记作 \(x = b^{-1}\)

思路

根据 \(\dfrac{a}{b} \bmod p = (a \times x) \bmod p\) 可以写出同余方程:\(\dfrac{a}{b} \equiv a \times x \pmod{p}\)

两边同时乘以 \(\dfrac{b}{a}\) 可以得到:\(bx \equiv 1 \pmod{p}\);或者可以理解为 \(x\) 在模 \(p\) 意义下等价于 \(\dfrac{1}{b}\)

转化一下就是 \(xb + kp = 1\),而 \(xb + kp = \gcd(b, p)\)
因此逆元并不是普遍存在的,条件是 \(\gcd(b, p) = 1\),也就是 \(b\)\(p\) 互质。

扩展欧几里得算法求逆元

上面已经得到了 \(bx \equiv 1 \pmod{p}\)\(xb + kp = 1\),而这就是上面讲到的特殊化的线性同余方程,可以使用扩展欧几里得算法求逆元。

详见上面:线性同余方程。

快速幂求逆元

前置知识:快速幂、费马小定理

\(p\) 为素数,\(\gcd(a, p) = 1\),则 \(a^{p - 1} \equiv 1 \pmod{p}\)
证明见:https://oi-wiki.org/math/number-theory/fermat/

仅当 \(p\) 是质数时,即 \(\gcd(b, p) = 1\) 时,也可以用快速幂求逆元:

上面已得 \(bx \equiv 1 \pmod{p}\)
根据费马小定理,\(b^{p - 1} \equiv 1 \pmod p\)
可以转化为 \(b \times b^{p - 2} \equiv 1 \pmod p\)
而我们要求的是 \(bx \equiv 1 \pmod p\)

因此可得 \(x = b^{p - 2}\)

代码实现

// s1: exgcd
int inv1(int a, const int p) {
    int x, y;
    exgcd(a, p, x, y);
    return (x % p + p) % p;
}
// s2: pow
int inv2(int a, const int p) {
    return quick_pow(a, p - 2, p);
}

线性求逆元

线性求任意 n 个数的逆元

给定长度为 \(n\) 的序列 \(a\)\(1 \le a_i < p\)),求序列每个数的逆元。

  • \(a_i\),表示原序列,即给定的序列;
  • \(\displaystyle s_i = \prod_{i = 1}^n a_i\),表示原序列的前缀积。
  • \(inv_i = {a_i}^{-1}\),表示原序列的乘法逆元,即待求的序列;
  • \(\displaystyle sv_i = {s_i}^{-1} = \prod_{i = 1}^n sv_i\),表示原序列前缀积的乘法逆元,根据逆元性质也等于原序列乘法逆元的前缀积。
  1. 计算给定序列 \(a_i\) 的前缀积,记为 \(s_i\)
  2. 使用快速幂或扩展欧几里得法计算 \(s_n\) 的逆元,记为 \(sv_n\)
  3. 因为 \(sv_n\)\(n\) 个数的积的逆元,所以当我们把它乘上 \(a_n\) 时,就会和 \(a_n\) 的逆元抵消;这样就得到了 \(a_1\)\(a_{n - 1}\) 的积逆元,记为 \(sv_{n - 1}\)
  4. 同理我们可以依次计算出所有的 \(sv_i\),于是 \({a_i}^{-1}\) 就可以用 \(s_{i - 1} \times sv_i\) 求得。

所以我们就在 \(O(n + \log p)\) 的时间内计算出了 \(n\) 个数的逆元。

// 计算前缀积
s[0] = 1;
for (int i = 1; i <= n; ++i) s[i] = s[i - 1] * a[i] % p;
// 计算全部乘法逆元的前缀积
sv[n] = quick_pow(s[n], p - 2, p);
// 递推前缀积、求序列的乘法逆元
for (int i = n; i >= 1; --i) sv[i - 1] = sv[i] * a[i] % p;
for (int i = 1; i <= n; ++i) inv[i] = sv[i] * s[i - 1] % p;
来自 OI-Wiki 的代码
s[0] = 1;
for (int i = 1; i <= n; ++i) s[i] = s[i - 1] * a[i] % p;
sv[n] = qpow(s[n], p - 2);
// 当然这里也可以用 exgcd 来求逆元,视个人喜好而定.
for (int i = n; i >= 1; --i) sv[i - 1] = sv[i] * a[i] % p;
for (int i = 1; i <= n; ++i) inv[i] = sv[i] * s[i - 1] % p;

特化:线性求 1 ~ n 的逆元

即原序列 \(a_i = i\),此时有更加快速的方法,但是这里不讲(见 OI-Wiki 内)。

我们在此就简化原程序。

s[0] = 1;
for (int i = 1; i <= n; ++i) s[i] = s[i - 1] * i % p;
sv[n] = quick_pow(s[n], p - 2, p);
for (int i = n; i >= 1; --i) sv[i - 1] = sv[i] * i % p;
for (int i = 1; i <= n; ++i) inv[i] = sv[i] * s[i - 1] % p;

例题

线性同余方程

点击查看代码

题目:P1082 同余方程

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

int main()
{
    ll a = rr, b = rr;
    ll x = 0, y = 0;

    exgcd(a, b, x, y);
    printf("%lld", (x % b + b) % b);
    return 0;
}

快速幂求逆元

点击查看代码

题目:P2613 有理数取余

const ll MOD = 19260817;

ll qpow(ll a, ll b, const ll p, ll res = 1)
{
    for (; b; b >>= 1)
        b & 1 ? res = res * a % p, a = a *a % p : a = a * a % p;
    return res;
}

int main()
{
    ll a = read(), b = read();
    if (b == 0)
        printf("Angry!\n"), exit(0);
    ll res = a * qpow(b, MOD - 2, MOD) % MOD;
    printf("%lld\n", res);
    return 0;
}

线性求 1 ~ n 的逆元

点击查看代码

题目:P3811 模意义下的乘法逆元

typedef long long ll;

const int N = 3e6 + 10;

ll s[N], sv[N];

ll qpow(ll a, ll b, const ll p, ll r = 1)
{
    for (; b; b >>= 1)
        b & 1 ? r = r * a % p, a = a * a % p : a = a * a % p;
    return r;
}

int main()
{
    const int n = rr;
    const ll p = rr;

    s[0] = 1;
    for (int i = 1; i <= n; ++i)
        s[i] = s[i - 1] * i % p;

    sv[n] = qpow(s[n], p - 2, p);
    for (int i = n; i; --i)
        sv[i - 1] = sv[i] * i % p;

    for (int i = 1; i <= n; ++i)
        printf("%lld\n", sv[i] * s[i - 1] % p);
    return 0;
}

线性求 n 数的逆元

点击查看代码

题目:P5431 模意义下的乘法逆元 2

求:\(\sum\limits_{i = 1}^n \frac{k^i}{a_i}\).

typedef long long ll;

const int N = 5e6 + 10;

ll a[N];
ll s[N], sv[N];

ll qpow(ll a, ll b, const ll p, ll r = 1)
{
    for (; b; b >>= 1)
        b & 1 ? r = r * a % p, a = a *a % p : a = a * a % p;
    return r;
}

int main()
{
    const int n = rr;
    const ll p = rr, k = rr;

    s[0] = 1;
    for (int i = 1; i <= n; ++i)
        a[i] = rr, s[i] = s[i - 1] * a[i] % p;

    sv[n] = qpow(s[n], p - 2, p);
    for (int i = n; i; --i)
        sv[i - 1] = sv[i] * a[i] % p;

    ll res = 0, kt = k;
    for (int i = 1; i <= n; ++i)
        res = (res + kt * (sv[i] * s[i - 1] % p) % p) % p, kt = kt * k % p;

    printf("%lld\n", res);
    return 0;
}

Reference

[1] https://oi-wiki.org/math/number-theory/fermat/
[2] https://oi-wiki.org/math/number-theory/inverse/
[3] https://oi-wiki.org/math/number-theory/linear-equation/文章来源地址https://www.toymoban.com/news/detail-710208.html

到了这里,关于数论——线性同余方程、乘法逆元 学习笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 线性代数:齐次线性方程组学习笔记

    齐次线性方程组是指所有方程的常数项均为零的线性方程组,即形如 A x = 0 Ax=0 A x = 0 的方程组。 其中,矩阵 A A A 是一个 m × n m times n m × n 的矩阵,向量 x x x 是一个 n n n 维列向量, 0 mathbf{0} 0 是一个 m m m 维零向量。 齐次线性方程组有以下性质: 1. 性质1 齐次线性方程组的

    2024年01月20日
    浏览(49)
  • 【学习笔记】求解线性方程组的G-S迭代法

    matlab中调用上述函数结果显示: 哪里出问题了啊?

    2024年02月10日
    浏览(35)
  • 线性代数学习笔记(二十九)——方程组解的结构(一)

    停更2年多了,做事得有始有终,继续更新。。。 本篇笔记回顾了线性方程组解的三种情况,并讨论了齐次线性方程组解的结构,并介绍了齐次线性方程组解的相关性质。其中重点讨论了基础解系定义,以及基础解系的求法和解题步骤,并对基础解系结果进行验证;还讨论了

    2024年02月09日
    浏览(47)
  • 线性代数学习笔记4-1:线性方程组的数学和几何意义、零空间/解空间/核

    求解方程 A x ⃗ = v ⃗ mathbf Avec x=vec v A x = v 首先说明系数矩阵的 行数和列数的意义 : 对于系数矩阵 A mathbf A A ,其行数代表方程个数,列数代表未知量个数 对于系数矩阵 A mathbf A A ,矩阵对应线性变换 矩阵 行数 代表变换后的基向量、 x ⃗ vec x x 和 v ⃗ vec v v 等向量的

    2024年02月02日
    浏览(47)
  • 人工智能基础_机器学习006_有监督机器学习_正规方程的公式推导_最小二乘法_凸函数的判定---人工智能工作笔记0046

    我们来看一下公式的推导这部分比较难一些, 首先要记住公式,这个公式,不用自己理解,知道怎么用就行, 比如这个(mA)T 这个转置的关系要知道 然后我们看这个符号就是求X的导数,X导数的转置除以X的导数,就得到单位矩阵, 可以看到下面也是,各种X的导数,然后计算,得到对应的矩阵

    2024年02月08日
    浏览(52)
  • MATLAB数值分析学习笔记:线性代数方程组的求解和高斯消元法

    工程和科学计算的许多基本方程都是建立在守恒定律的基础之上的,比如质量守恒等,在数学上,可以建立起形如 [A]{x}={b} 的平衡方程。其中{x}表示各个分量在平衡时的取值,它们表示系统的 状态 或 响应; 右端向量{b}由无关系统性态的常数组成通常表示为 外部激励。 矩阵

    2023年04月15日
    浏览(61)
  • MATLAB数值分析学习笔记:线性代数方程组的求解和高斯-赛德尔方法

    迭代法是前面介绍的消元法的有效替代,线性代数方程组常用的迭代法有 高斯-赛德尔方法 和 雅克比迭代法, 下面会讲到二者的不同之处,大家会发现两者的实现原理其实类似,只是方法不同,本篇只重点介绍高斯-赛德尔方法。 看了我之前的笔记的同学应该已经对迭代法不

    2024年02月05日
    浏览(58)
  • 乘法逆元(inverse element)及四大相关求法详解(含证明)

    知识的补缺是老生常谈的一大问题,随着自身学习进程的推进,越发觉着逆元知识的重要,故此我站在网上各路大牛的肩膀上,对此知识进行一定程度上的系统梳理。如有不足之处,还请大家指出,大家共同进步,互利共赢 !! 先呈上菜: 很明显,上述式子只有一条不成立

    2023年04月15日
    浏览(34)
  • 人工智能基础_机器学习003_有监督机器学习_sklearn中线性方程和正规方程的计算_使用sklearn解算八元一次方程---人工智能工作笔记0042

    然后我们再来看看,如何使用sklearn,来进行正规方程的运算,当然这里 首先要安装sklearn,这里如何安装sklearn就不说了,自己查一下 首先我们还是来计算前面的八元一次方程的解,但是这次我们不用np.linalg.solve这个 解线性方程的方式,也不用 直接 解正规方程的方式: 也就是上面这种

    2024年02月08日
    浏览(52)
  • 2023.7.26(同余方程的通解与特解)

    Water(扩欧求特解与通解) 题意:给容量分别为A与B的水杯,问确切喝到C水的最小操作次数 有4种操作:选一杯全喝,选一杯全部倒掉,选一杯装满,将一杯的水尽量倒到另一杯中 思路:只有Ax+By=C有解时才能确切喝到X水 裴蜀定理:如果a、b是整数,那么一定存在整数x、y使得

    2024年02月15日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包