码迷,mamicode.com
首页 > 其他好文 > 详细

浅谈乘法逆元

时间:2018-12-22 22:07:13      阅读:274      评论:0      收藏:0      [点我收藏+]

标签:时间   class   math   oid   mat   直接   数组   最简   void   

浅谈乘法逆元

乘法逆元,一般用于求解\(\frac{A}{C}(mod ~ P)\)的值,因为我们通过模的定义可以知道上式显然不等于\(\frac{A \% P}{B \% P}\)。例子有很多不再举了。那么如果我们要求上式大多数情况都需要借助逆元。

首先是定义:

\(A \times X \equiv 1 (mod ~ P)\),并且\(A \perp P\)(\(\perp\):互质),那么我们就称\(X\)\(A\)的逆元,简称为\(A^{- 1}\),也就是\(A\)\(mod ~ P\)意义下的倒数。

借此我们可以知道\(\frac{A}{C}(mod ~ P)\)的求法:我们先求出\(C\)\(mod ~ P\)意义下的逆元,然后\(\times A\)就是答案了。那么我们主要求的就是\(C\)的逆元。

扩展欧几里得版

首先从最简单开始,就是一个扩展欧几里得,直接求解\(A \times X + P \times Y = 1\)就行了。

inline void Exgcd(int A, int P, int X, int Y) {
    if (! B) X = 1, Y = 0 ;
    else Exgcd(P, A % P, Y, X), Y -= A / B * X ;
}

这个方法虽然时间上比较慢,但是有一个优点,就是当\(A\)\(P\)不互质的时候,依然可以适用。但是下面介绍的其他方法就必须满足\(A \perp P\)了。

费马小定理版

回顾一下费马小定理的内容:

\(A \perp P\), 则\(A^{P - 1} \equiv 1(mod ~ P)\)

我们可以把它运用到乘法逆元里。结合\(A \times X \equiv 1(mod ~ P)\)可以得到\(A \times X \equiv A^{P - 1}(mod ~ P)\)。当\(P\)为质数的时候,我们把左右都除以一个\(A\)可以得到\(X \equiv A^{P - 2}(mod P)\)。然后就可以一个快速幂求出来了。

inline void Fpm(int A, int P) {
    int Ans = 1 ; int M = P ;
    A %= M ; P -= 2 ;
    while (P) {
        if (P & 1) Ans = Ans * A % M ;
        A = A * A % M ; P >> = 1 ;
    }   return Ans % M ;
}

上面的复杂度是\(O(logN)\)的,在求多个逆元的时候可能\(O(NlogN)\)是过不去的。当然我们还有一种利用地推打出逆元表的方法做到\(O(N)\).

欧拉筛版

\(INV[i]\)\(i\)的逆元。我们知道有\(INV[A] = A ^ {P - 2}(mod ~ P),~INV[B] = B ^ {P - 2} (mod ~ P)\)

我们利用费马小定理可以得\(INV[A \times B] = (AB) ^ {P - 2} (mod P)\)也就是说\(INV[A \times B] = INV[A] \times INV[B]\)。求得递推式。我们就可以利用欧拉筛。

递推版

为了方便起见就直接写过程了。

\(P = kA + r~~(r \in [0, P)~)\)。因为我们知道任何一个数都可以写成这个形式嘛。

那么有\(kA + r \equiv 0 (mod ~ P)\)

因为\(A^{P - 1} \equiv 1(mod ~ P)\)

所以\((kA +r) \times A^{- 1} \times r^{- 1} \equiv 0 (mod ~ P)\)

把左边的括号拆开得\(kr^{- 1} + A^{- 1} \equiv 0 (mod ~ P)\)

移项:\(A^{- 1} \equiv -kr^{- 1}\)

在这里我们知道\(k = \lfloor \frac{P}{A} \rfloor\)

\(A^{- 1} \equiv -\lfloor \frac{P}{A} \rfloor \times r^{- 1}\)

并且我们还知道\(r ≤ A\)。那么我们就可以借用数组\(INV[r]\)完成递推。同时我们还知道\(r = P \% A\)

最后得到\(INV[A] = (P - \lfloor \frac{P}{A} \rfloor) \times INV[P\% A]\)

递推完成,时间复杂度\(O(N)\)

for (int i = 2 ; i <= N ; i ++)
        INV[i] = P - (P / i) * INV[P % i] % P;

当然不要忘了初始化的问题。

浅谈乘法逆元

标签:时间   class   math   oid   mat   直接   数组   最简   void   

原文地址:https://www.cnblogs.com/Yeasio-Nein/p/INV.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!