P3811 【模板】模意义下的乘法逆元

题目描述


给定正整数 \(n,p\),求 \([1,n]\) 中所有整数在模 \(p\) 意义下的乘法逆元。
\(a\) 模 \(p\) 的乘法逆元定义为 \(ax\equiv1\pmod p\) 的解。

扩展欧几里得算法


#include <iostream>

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

int main() {
    int n = 0;
    int p = 0;
    // std::cin >> n >> p;
    scanf("%d %d", &n, &p);
    for (int i = 1; i <= n; i++) {
        int x = 0;
        int y = 0;
        int d = exgcd(i, p, x, y); // ix + py = 1
        x %= p;
        if (x < 0) x += p;
        // std::cout << x << std::endl;
        printf("%d\n", x);
    }
    return 0;
}
  • 遍历\(i=1,\cdots,p-1\),针对于每一个\(i\)使用扩展欧几里得算法求解\(ix+py=gcd(i,p)=1\)的解,对于其中的\(x\)规约到\(p\)的简化剩余系中即可,这个代码有一个样例过不了。
  • 时间复杂度:\(O(n\ log\ p)\)
  • 空间复杂度:\(O(1)\)

线性递推求逆元


将\(p\)对\(i\)进行带余除法:\((p\ is\ a\ prime)\ and\ (i<p)\rightarrow p=k\cdot i+r(0<r<i)\),其中\(k=\lfloor {p\over i}\rfloor\),\(r=p\% i\)。

\[\begin{flalign} & p=k\cdot i + r\rightarrow k\cdot i + r\equiv0\pmod{p}\rightarrow k\cdot i\equiv -r\pmod{p}\\ & \xrightarrow[\times r^{-1}\pmod{p}]{\times i^{-1}\pmod{p}}k\cdot r^{-1}\equiv -i^{-1}\pmod{p}\rightarrow i^{-1}\equiv -k\cdot r^{-1} = -\lfloor{p\over i}\rfloor\cdot (p \% i)^{-1}\pmod{p}\\ & \rightarrow i^{-1}\equiv (p-\lfloor{p\over i}\rfloor)\cdot(p\%i)\pmod{p} \end{flalign} \]

#include <iostream>
#include <vector>

int main() {
    int n = 0;
    int p = 0;
    scanf("%d %d", &n, &p);
    std::vector<int> inv(n + 1, 0);
    inv[1] = 1;
    for (int i = 2; i <= n; i++) {
        inv[i] = (long long)(p - p / i) * inv[p % i] % p;
    }
    for (int i = 1; i <= n; i++) {
        printf("%d\n", inv[i]);
    }
    return 0;
}
  • 时间复杂度:\(O(n)\)
  • 空间复杂度:\(O(n)\)
posted @ 2026-09-07 21:49  chen_xing  阅读(7)  评论(0)    收藏  举报