乘法逆元总结

乘法逆元问题,常常以这这样的形式出现

  a/mod )=a*(p1)( mod p),b是关于p的逆元。

求解乘法逆元的几种方法:

1 费马小定理,a在模p下的逆元,要求p为质数。

ll fpm(ll x, ll power, ll mod) {
    x %= mod;
    ll ans = 1;
    for (; power; power >>= 1, (x *= x) %= mod)
        if(power & 1) (ans *= x) %= mod;
    return ans;
}
int main() {
    ll x = fpm(a, p - 2, p); //x为a在mod p意义下的逆元
}

2 拓展欧几里得。

  exgcd,求a在模p下的逆元,要求a和p互质,但是p不一定是质数。

  code:

void Exgcd(ll a, ll b, ll &x, ll &y) {
    if (!b) x = 1, y = 0;
    else Exgcd(b, a % b, y, x), y -= a / b * x;
}
int main() {
    ll x, y;
    Exgcd (a, p, x, y);
    x = (x % p + p) % p;
    printf ("%d
", x); //x是a在mod p下的逆元
}

3 线性乘法

  常用于求一连串数字对于一个 mod p 的逆元。要求p为质数

  code:

inv[1] = 1;
for(int i = 2; i <=n; ++ i)
    inv[i] = (p - p / i) * inv[p % i] % p;

证明: p=k*i+r,对p取模可得,k*i+r=0(mod p),两端同时乘以i的逆元[i]和r的逆元[r]可得,k*[r]+[i]=0(mod p),

[i]=-k*[r]=-k*[p%i],k=p/i,所以[i]=(-p/i)*([p%i]),[i]=(p-p/i)*[p%i]%p;

4 递推法求阶乘逆元:

  code:

void init() {
    fact[0] = 1;
    for (int i = 1; i < maxn; i++) {
        fact[i] = fact[i - 1] * i %mod;
    }
    inv[maxn - 1] = power(fact[maxn - 1], mod - 2);
    for (int i = maxn - 2; i >= 0; i--) {
        inv[i] = inv[i + 1] * (i + 1) %mod;
    }
}

 证明过程:设n!的逆元为[n],我们求一下(n-1)!的逆元。

  n!*[n]=1(mod p)    将n!拆开, (n-1)!*n*[n]=1(mod p)所以,(n-1)!的逆元就是n[n]。

所以递推式inv[n]=inv[n+1]*(n+1)%p;

https://blog.csdn.net/qq_35416331/article/details/81059747

原文地址:https://www.cnblogs.com/Accepting/p/12582711.html