乘法逆元學習筆記
定義
當 \(a,b\) 滿足 \(ab \equiv 1\pmod p\) ,\(a,b\) 互為 \(\pmod p\) 的乘法逆元,也記作 \(a^{-1}\) 和 \(b^{-1}\) 。
前置知識
1.費馬小定理
若 \(p\) 為質數且 \(\gcd(a,p) = 1\) ,則 \(a, p\) 滿足 \(a^{p-1}\equiv 1 \pmod p\) 。
證明:
考慮下面兩個整數序列:
\[1,2,3,4,5......p-2,p-1 \] \[a,2a,3a,4a,5a.......(p-2)a,(p-1)a \]第一個序列很明顯每個數對 \(p\) 取餘各不相同,且為 \(1\)
對於第二個序列,如果有兩個不同的數 \(ax\) ,\(ay\) 使得 \(ax\equiv ay \pmod p\) ,則 \(p|a|x-y|\) 。
\(\because\) \(\gcd(a,p)=1\) , \(\therefore\) \(p||x-y|\) 。
又 \(\because\) \(x,y < p\) 且 \(x \not= y\) , \(\therefore\) \(0<|x-y|<p\) ,\(p \not| \,|x-y|\) ,矛盾。
\(\therefore\) 第二個序列每個數對 \(p\) 取餘都不相同, 且不為 \(0\)
\(\therefore\) 第二個序列中 \(p-1\) 個數對 \(p\) 取模為 \(1\) 到 \(p-1\) 各一個。
現在把第一個序列的數和第二個序列的數各自相乘,得到:
\[(p-1)!\equiv a^{p-1}(p-1)! \pmod p \]\(\because\) \((p-1)!\) 與 \(p\) 互質。\(\therefore\) 可以把兩邊同時除以 \((p-1)!\) 得到:
\[a^{p-1}\equiv 1\pmod p \]得證。
2.尤拉定理
若 \(a,p\) 滿足 \(\gcd(a,p)=1\) ,則 \(a^{\phi(p)}\equiv 1 \pmod p\)
證明:
與上面類似,考慮下面兩個整數序列:
\[x_1,x_2,x_3,x_4,x_5......x_{\phi(p)-1},x_{\phi(p)} \] \[ax_1,ax_2,ax_3,ax_4,ax_5.......ax_{\phi(p)-1},ax_{\phi(p)} \]第一個序列是模 \(p\) 意義下的一個簡化剩餘系,則第二個序列也為模 \(p\) 意義下的一個簡化剩餘系,把兩個序列的數各自相乘得到:
\[\prod_{i=1}^{\phi(p)}x_i\equiv a^{\phi(p)} \times \prod_{i=1}^{\phi(p)}x_i \pmod p \]\(\because\) \(\prod_{i=1}^{\phi(p)}x_i\) 與 \(p\) 互質。\(\therefore\) 可以把兩邊同時除以 \((p-1)!\) 得到:
\[a^{\phi(p)}\equiv1\pmod p \]得證。
如何求逆元
我們現在要求 \(a\) 在 \(\bmod \,p\) 意義下的逆元,即方程 \(ax\equiv 1 \pmod p\) 的解。
1.當 \(p\) 是質數且 \(\gcd(a,p)=1\) 時,根據費馬小定理可得:
\[a^{p-1}\equiv 1 \pmod p \] \[a \times a^{p-2} \equiv 1\pmod p \]\(\therefore\) \(a\) 的逆元就是 \(a^{p-2}\) ,可以用快速冪求,時間複雜度 \(O(\log p)\) 。
2.當 \(\gcd(a,p)=1\) 時,根據尤拉定理可得:
\[a^{\phi(p)}\equiv 1 \pmod p \] \[a \times a^{\phi(p)-1} \equiv 1\pmod p \]\(\therefore\) \(a\) 的逆元就是 \(a^{\phi(p)-1}\),其中尤拉函式 \(\phi\) 可以在 \(O(\sqrt p)\) 的時間算出來(不過好像也有一些玄學的演算法,但 \(p\) 的範圍一般不會爆 int ,所以這也夠了), 而快速冪的時間是 \(O(\log p)\) 。
逆元的作用
我們知道,餘數有可加性,可減性,可乘性,但沒有可除性,當要對分數取模時,逆元就派上用場。
分數 \(\dfrac{a}{b}\) 對 \(p\) 取模的結果相當於 \(a \times b^{-1}\pmod p\) ,也就是分子乘上分母在模 \(p\) 意義下的逆元,這樣就可以對分數取模了。
注意,求逆元的時間複雜度是 \(O(\log p)\) ,所以求逆元的次數越少越好。
線性求逆元
有時候我們需要以 \(O(n)\) 的複雜度求出 \(1\) 到 \(n\) 所有數在模 \(p\) 意義下的逆元,這時候一個一個求的複雜度就變為 \(O(n \log p)\) 了,我們需要用別的方法 \(O(n)\) 的求逆元。
以 P3811 【模板】乘法逆元 為例
題目要求求出 \(1\) 到 \(n\) 所有數在模 \(p\) 意義下的逆元,我們考慮如何遞推逆元。
設我們當前正在求 \(a\) 的逆元,並且已經求出 \(1\) 到 \(a-1\) 的逆元,現在要以 \(O(1)\) 的時間複雜度推出 \(a\) 的逆元。我們可以做一個帶餘除法:
\[p \div a = b ......r \]變成等式:
\[a \times b + r = p \]這個式子在模 \(p\) 意義下變為:
\[a \times b + r \equiv 0 \pmod p \]而 \(r < a\) ,所以我們已經知道 \(r^{-1}\) ,現在我們給式子乘上一個 \(a^{-1}r^{-1}\) :
\[a \times b \times a^{-1} \times r ^{-1} + r \times r^{-1} \times a^{-1}\ \equiv 0 \pmod p \]\(a\) 與 \(a^{-1}\) 和 \(r\) 與 \(r^{-1}\) 相乘都變成 \(1\) ,所以:
\[b \times r^{-1} + a^{-1} \equiv 0 \pmod p \] \[a^{-1} \equiv -b \times r^{-1} \pmod p \]這樣我們就推出了 \(a\) 的逆元,總時間複雜度 \(O(n)\) 。
階乘逆元
組合數的公式是 \(C_n^m = \frac{n!}{m!(n-m)!}\) ,當我們需要對一個組合數取模,必須先把組合數算出來再取模,而算的過程中是無法取模的,但階乘又很大,所以我們就需要用到階乘的逆元。階乘的逆元也可以 \(O(n)\) 的遞推,但是是倒著推。
設我們當前正在求 \(k!\) 的逆元,已經求出了 \((k+1)!\) 到 \(n!\) 的逆元,我們知道:
\[(k+1)![(k+1)!]^{-1} \equiv 1 \pmod p \]把 \((k+1)!\) 拆成 \(k!\) 和 \((k+1)\),可得:
\[k! \times (k+1)[(k+1)!]^{-1}\equiv 1 \pmod p \]\(\therefore\) \((k!)^{-1}=(k+1)[(k+1)!]^{-1}\) ,然後我們就可以 \(O(n)\) 的遞推了,但是首先我們要求出 \(n!\) ,這就可以用費馬小定理或者尤拉定理直接求即可。
一些題目
題意:給你 \(3\) 個數 \(n,p,k\) 和一個長度為 \(n\) 序列 \(a\) ,求出
\(\sum_{i=1}^n\frac{k^i}{a_i}\)
對 \(p\) 取模的值。
思路:
樸素的求每一項的值時間複雜度是 \(O(n \log p)\) 的,而 \(n,p\) 都很大,而且這題卡的很死,所以考慮如何優化。
為了減少求逆元的次數,我們可以直接通分,然後就變成了下面這個樣子:
\[\frac{\sum_{i=1}^{n}{(k^i\times\prod^{i-1}_{j=1}a_i\times\prod_{j=i+1}^na_i})}{\prod_{i=1}^na_i} \]這樣我們就可以我們可以先計算出分子和分母,再求一次逆元即可。我們可以 \(O(n)\) 的求出 \(a\) 的字首積和字尾積以及 \(k\) 的冪次方,最後統計答案即可,時間複雜度 \(O(n + \log p)=O(n)\) 。