乘法逆元板子(找不到出处)

乘法逆元

如果一个线性同余方程 a x ≡ 1 ( m o d   n ) ax\equiv 1(mod\ n) ax1(mod n),则 x x x称为 a   m o d   n a\ mod\ n a mod n的逆元,记作 a − 1 a^{-1} a1

扩展欧几里得算法求逆元

g c d ( a , n ) ≠ 1 gcd(a,n)\not ={1} gcd(a,n)=1,则方程无解。所以如果方程有解的话,就可以通过扩展欧几里得算法求逆元。

快速幂法求逆元

根据费马小定理,若 n n n 为素数,且 g c d ( a , n ) = 1 gcd(a,n)=1 gcd(a,n)=1 a   m o d   n a\ mod\ n a mod n的逆元可以计算为 a n − 2 a^{n-2} an2,可通过快速幂求解。

1 , 2 , ⋯   , n 1,2,\cdots,n 1,2,,n中每个数关于 p p p的逆元

算法时间复杂度为 O ( n ) O(n) O(n)

gg inv[MAX];
void invEle(gg n, gg p) {
    inv[1] = 1;
    for (gg i = 2; i <= n; ++i) {
        inv[i] = (p - p / i) * inv[p % i] % p;
    }
}

求任意 n n n 个数关于 p p p的逆元

首先计算 n 个数的前缀积,记为 s i s_i si,然后利用快速幂或扩展欧几里得算法计算 s n s_n sn的逆元,记作 s v n sv_n svn。因为 s v n sv_n svn 是 n 个数的积的逆元,所以当我们把它乘上 a n a_n an 时,就会和 a n a_n an 的逆元抵消,于是就得到了 a 1 a_1 a1 a n a_n an 的积逆元,记为 s v n − 1 sv_{n-1} svn1。可以依次计算出所有的 s v i sv_i svi ,于是 a i − 1 a_i^{-1} ai1 就可以用 s i − 1 ⋅ s v i s_{i-1}\cdot sv_i si1svi 求得。算法时间复杂度为 O ( n + l o g   p ) O(n+log\ p) O(n+log p)

gg inv[MAX], s[MAX], a[MAX], sv[MAX];
void invEle(gg n, gg p) {
    s[0] = 1;
    for (gg i = 1; i <= n; ++i) {
        s[i] = s[i - 1] * a[i] % p;
    }
    //也可以用扩展欧几里得来求逆元,视个人喜好而定.
    sv[n] = powMod(s[n], p - 2, p);
    for (gg i = n; i >= 1; --i) {
        sv[i - 1] = sv[i] * a[i] % p;
    }
    for (gg i = 1; i <= n; ++i) {
        inv[i] = sv[i] * s[i - 1] % p;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值