模素数意义下的乘法逆元

模意义下的乘法逆元

乘法逆元的定义

\(ax \equiv 1 \pmod p\),则称 \(x\)\(a\) 在模 \(p\) 意义下的乘法逆元,记作 \(a^{-1}\)

\(p \in \mathbb{P}\) 时,求乘法逆元的方法:

利用费马小定理。

根据费马小定理,当 \(p\) 为素数时,有 \(a^{p-1} \equiv 1 \pmod p\)
注意到 \(a \times a^{p - 2} \equiv a^{p - 1} \equiv 1 \pmod p\)
\(a^{p - 2}\)\(a\) 在模 \(p\) 意义下的一个逆元。
\(p \in \mathbb{P}\) 时,可以用快速幂来求逆元。

点击查看代码
LL QuickPower(LL a, LL b) {
    LL ans = 1;
    while (b) { if (b & 1) ans *= a; a *= a; b >>= 1; }
    return ans;
}

int Inverse = QuickPower(a, p - 2);
线性求逆元

若求从 \(1\)\(p\) 的逆元,可用该方法。

假设 \(1\)\(i - 1\) 的逆元都已知。设 \(k = \left\lfloor\dfrac{p}{i}\right\rfloor, r = p \bmod i\)。则 \(ki + r \equiv 0 \pmod p\),两边同时除以 \(ir\),得 \(kr^{-1}+i^{-1} \equiv 0 \pmod p\),即 \(i^{-1} \equiv -kr^{-1}\equiv \left\lfloor\dfrac{p}{i}\right\rfloor \times (p \bmod i)^{-1}\)

类似于 dp ,时间复杂度为 \(O(n)\)

点击查看代码
inv[1] = 1;
for (int i = 2; i <= p; i++) inv[i] = p / i + inv[p % i];
线性求 \(n\) 个数的逆元

\(n\) 个数的逆元可用此方法 \((1 \le a_i \lt p)\)

\(s\) 为数组 \(a\) 的前缀积。计算出 \(s_n^{-1}\)\(1\)\(n\) 的逆元积,后通过 \(s_i^{-1} = s_{i + 1}^{-1} \times a_{i +1}\) 即可得到前 \(i\) 项逆元积,则 \(a_i^{-1} = s_{i - 1} \times s_i^{-1}\)

时间复杂度为 \(O(n + \log p)\)

点击查看代码
LL s[N], s_inv[N], a[N], a_inv[N];
int n, p;

LL QuickPower(LL a, LL b) {
    LL ans = 1;
    while (b) { if (b & 1) ans *= a; a *= a; b >>= 1; }
    return ans;
}

cin >> n >> p;
s[0] = 1;
for (int i = 1; i <= n; i++) cin >> a[i], s[i] = a[i] * s[i - 1];
s_inv[n] = QuickPower(s[i], p - 2);
for (int i = n - 1; i >= 1; i--)  s_inv[i] = s_inv[i + 1] * a[i + 1];
for (int i = 1; i <= n; i++) a_inv[i] = s[i - 1] * s_inv[i];

参考资料

oi-wiki
Alew_Wei神牛的blog

你是个独立的人,无人能抹杀你的独立性,除非你向世俗妥协。

posted @ 2024-08-06 21:25  FRZ_29  阅读(2)  评论(0编辑  收藏  举报