乘法逆元


乘法逆元小結

乘法逆元,一般用於求 $$\frac{a}{b} \pmod p$$ 的值(\(p\) 通常為質數),是解決模意義下分數數值的必要手段。

有興趣可以點進我的博客看看啊qwq

逆元定義

\(a*x\equiv1 \pmod {b}\),且\(a\)\(b\)互質,那么我們就能定義:
\(x\)\(a\) 的逆元,記為\(a^{-1}\),所以我們也可以稱 \(x\)\(a\)\(\bmod b\) 意義下的倒數,

所以對於 \(\displaystyle\frac{a}{b} \pmod {p}\) ,我們就可以求出 \(b\)\(\bmod {p}\) 下的逆元,然后乘上 \(a\) ,再 \(\bmod {p}\),就是這個分數的值了。

求解逆元的方式

拓展歐幾里得

這個方法十分容易理解,而且對於單個查找效率似乎也還不錯,比后面要介紹的大部分方法都要快(尤其對於 \(\bmod {p}\) 比較大的時候)。

這個就是利用拓歐求解 線性同余方程 \(a*x \equiv c \pmod {b}\)\(c=1\)的情況。我們就可以轉化為解 \(a*x + b*y = 1\) 這個方程。

求解這個方程的解。不會拓歐可以點這里~

而且這個做法還有個好處在於,當 \(a \bot p\) (互質),但 \(p\) 不是質數的時候也可以使用。

代碼比較簡單:

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\n", x); //x是a在mod p下的逆元
}

快速冪

這個做法要利用 費馬小定理

\(p\)為素數,\(a\)為正整數,且\(a\)\(p\)互質。
則有\(a^{p-1} \equiv 1 (\bmod {p})\)

這個我們就可以發現它這個式子右邊剛好為 \(1\)

所以我們就可以放入原式,就可以得到:

\[a*x\equiv 1 \pmod p \]

\[a*x\equiv a^{p-1} \pmod p \]

\[x \equiv a^{p-2} \pmod p \]

所以我們可以用快速冪來算出 \(a^{p-2} \pmod 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意義下的逆元
}

線性算法

用於求一連串數字對於一個\(\bmod p\)的逆元。洛谷P3811

只能用這種方法,別的算法都比這些要求一串要慢。

首先我們有一個,\(1^{-1}\equiv 1 \pmod p\)

然后設 \(p=k*i+r,(1<r<i<p)\) 也就是 \(k\)\(p / i\) 的商,\(r\) 是余數 。

再將這個式子放到\(\pmod p\)意義下就會得到:

\[k*i+r \equiv 0 \pmod p \]

然后乘上\(i^{-1}\),\(r^{-1}\)就可以得到:

\[k*r^{-1}+i^{-1}\equiv 0 \pmod p \]

\[i^{-1}\equiv -k*r^{-1} \pmod p \]

\[i^{-1}\equiv -\lfloor \frac{p}{i} \rfloor*(p \bmod i)^{-1} \pmod p \]

於是,我們就可以從前面推出當前的逆元了。

代碼也很短:

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

階乘逆元 \(O(n)\)

因為有如下一個遞推關系。

\(\displaystyle inv[i+1]=\frac{1}{(i+1)!}\)

\(\displaystyle inv[i+1]*(i+1)=\frac{1}{i!}=inv[i]\)

所以我們可以求出\(n!\)的逆元,然后逆推,就可以求出\(1...n!\)所有的逆元了。

遞推式為

\(inv[i+1]*(i+1)=inv[i]\)

所以我們可以求出 \(\displaystyle \forall i, i!,\frac{1}{i!}\) 的取值了。

然后這個也可以導出 \(\displaystyle \frac{1}{i} \pmod p\) 的取值,也就是

\[\displaystyle \frac{1}{i!} \times (i - 1)! = \frac{1}{i} \pmod p \]

具體實現可以參考我這發提交(卡了常。。)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM