浅谈 逆元乘法逆元
逆元
除以一個(gè)數(shù)再取模 = 乘以這個(gè)數(shù)的逆元再取模
設(shè) inv[b] 是b的逆元,則(a/b) mod p = (a * inv[b]) mod p
(1)一個(gè)數(shù)的逆元是什么? ?一個(gè)數(shù)x在模p的條件下的逆元是多少
(2)一個(gè)數(shù)的逆元有無窮個(gè),只求最小正整數(shù)即可
(3)一個(gè)數(shù)x在模p的條件下不一定有逆元,x關(guān)于p的逆元存在當(dāng)且僅當(dāng)x和p互質(zhì)
推導(dǎo):設(shè) a 為 x 的逆元,b 為任意整數(shù)? ? ?//證明 x 與 p 必須互質(zhì)
x * a?≡ 1 (mod p)
= x * a = 1 - b*p
= x * a +b * p = 1
若 x 與 p 不互質(zhì),則 x 和 p 存在公約數(shù) d = gcd(x,p) >1
提取出 d ,得到:d*(x div d*a + p div d*b)=1
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(x div d*a + p div d*b)= 1 div d? ? ? ? ? ?//移項(xiàng)
易知x,p能整除 d ,所以括號內(nèi)定為整數(shù)
又因?yàn)?d > 1,等式右邊必為真分?jǐn)?shù),等式無解
何為乘法逆元
對于兩個(gè)數(shù) a,p,若gcd(a,p)=1 (即a,p互質(zhì)),則一定存在另一數(shù)b,使得a*b?≡ 1(mod p) //上面已證
并稱此時(shí)的 b 為 a 關(guān)于 1 模 p 的乘法逆元,記 b 為 inv(a) 或 a^-1。
求逆元的方法
?
1.費(fèi)馬小定理
當(dāng)有兩個(gè)數(shù) a,p 滿足gcd(a,p)=1時(shí),則有 a^p ≡ a (mod p)
變形:a * a^(p-2)≡ 1(mod p)//和上面乘法逆元定義相似
所以,我們可以求出a^(p-2),即求出 a 的逆元。
當(dāng)p比較大的時(shí)候需要用快速冪求解
復(fù)雜度O(logn)
const int mod = 1000000009; long long pow(long long a,long long b) {if(b<0)return 0;long long res=1;a%=mod;while(b)//快速冪{if(b & 1)res=(res*a)%mod;b >>= 1;a=(a*a)%mod;}return res; } long long inv(long long a)//求逆元 {return pow(a,mod-2);//求a^(mod-2) }2.拓展歐幾里得算法
由定義可知:a * b?≡ 1 (mod p)
等價(jià)于已知a,p求一個(gè)二元一次方程組 a*b = k*p+1
移項(xiàng)得:a*b - k*p = 1
然后套用求二元一次方程的方法,用擴(kuò)展歐幾里得算法求得一組x0,y0和gcd?
檢查gcd是否為1?
gcd不為1則說明逆元不存在?
若為1,則調(diào)整x0到0~m-1的范圍中即可
PS:這種算法效率較高,常數(shù)較小,時(shí)間復(fù)雜度為O(ln n)
條件:可擴(kuò)展歐幾里得求逆元 ab≡1(mod p)其中a,p互質(zhì)
ll ecgcd(ll a,ll b,ll &x,ll &y) {if(b == 0)//終止條件{x = 1;y = 0;return a;}else {ll ans = ecgcd(b,a%b,x,y);//繼續(xù)遞歸下去ll temp = x;//暫且保存xx = y;y = y-a/b*temp;return ans;} } ll inv(ll a,ll n)//求逆元 {ll x,y;exgcd(a,n,x,y);//解二元一次方程組x = (x % n+n) % n;return x; }?
3.遞推計(jì)算階乘的逆元
當(dāng)我們計(jì)算一大串連續(xù)的階乘的逆元時(shí),采用費(fèi)馬小定理或擴(kuò)展歐幾里得就可能會(huì)時(shí)超,所以得采用一個(gè)更快的算法
令 f[i] = i!,可得:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? inv(f[i+1])≡ inv(f[i]*(i+1))? ? ? (mod p)
將(i+1)乘過去得:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? inv(f[i])≡ inv(f[i+1])* (i+1)? ? ? (mod p)
4.遞推計(jì)算連續(xù)的數(shù)的逆元:
當(dāng)我們要計(jì)算連續(xù)的數(shù)的逆元時(shí),我們可以采用一下遞推式:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
5.還有一種我也不知道的算法(盜的)
逆元打表法
有時(shí)會(huì)遇到這樣一種問題,在模質(zhì)數(shù)p下,求1~n逆元 n< p(這里為奇質(zhì)數(shù))。可以O(shè)(n)求出所有逆元,有一個(gè)遞推式如下
?
???????????????????
?
它的推導(dǎo)過程如下,設(shè),那么
?
???? ??
?
對上式兩邊同時(shí)除,進(jìn)一步得到
?
???????
?
再把和替換掉,最終得到
?
???????
?
初始化,這樣就可以通過遞推法求出1->n模奇素?cái)?shù)的所有逆元了。
還有一種???(不過好像就是我的第四種)
另外有個(gè)結(jié)論模的所有逆元值對應(yīng)中所有的數(shù),比如,那么對應(yīng)的逆元是。
const int n=le5+5; int inv[n]; void inverse(int n,int p) {inv[1]=1;for(int i=2 ; i<=n ;i++){inv[i]=(ll)(p-p/i)*inv[p%i]%p;} }總結(jié)
- 上一篇: 嵌入式系统设计(五):详细介绍win8/
- 下一篇: 工业机器人上半年产业分析