我們都知道除法不滿足取模,那么我們可以求模的逆元來進行求結果,既然乘法可以取模,如果這個數除以一個數,那么我們可以讓他乘以一個數使得和除以那個數的結果相同,那么乘的這個數就是那個數的乘法逆元。下面摘自Acdreamer的博客
今天我們來探討逆元在ACM-ICPC競賽中的應用,逆元是一個很重要的概念,必須學會使用它。
對於正整數
和
,如果有
,那么把這個同余方程中
的最小正整數解叫做
模
的逆元。
逆元一般用擴展歐幾里得算法來求得,如果
為素數,那么還可以根據費馬小定理得到逆元為
。
推導過程如下
求現在來看一個逆元最常見問題,求如下表達式的值(已知
)
![]()
當然這個經典的問題有很多方法,最常見的就是擴展歐幾里得,如果
是素數,還可以用費馬小定理。
但是你會發現費馬小定理和擴展歐幾里得算法求逆元是有局限性的,它們都會要求
與
互素。實際上我們還有一
種通用的求逆元方法,適合所有情況。公式如下
現在我們來證明它,已知
,證明步驟如下
下面是兩個求乘法逆元的模板
輾轉相除法求逆元(求a對於mod的逆元, 要求a與mod互素)
ll exgcd(ll a, ll b, ll &x, ll &y) { if (b == 0) { x = 1; y = 0; return a; } ll r = exgcd(b, a % b, x, y); ll t = x % mod; x = y % mod; y = ((t - a / b * y) % mod + mod) % mod; return r; } 求2對於1e9+7的逆元就是 exgcd(2, 1e9+7, x, y),其中x的值就是inv2,
費馬小定理求逆元(求a對於mod的逆元,要求mod為素數)
ll power_mod(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1) ans = ans * a % mod; a = a * a % mod; b >>= 1; } return ans; } inv2 = power_mod(a, mod - 2, mod);