大数求乘法逆元c语言,乘法逆元(编程计算)+两道版题
前言
看到這里的小盆友們千萬不要以為這個東西很難,其實就是個1+1->1(1個定義+1個定理->1坨乘法逆元).Let’s begin.web
有關乘法逆元定義
這個咱們就不要玩笑了,來,直接看定義:
乘法:是指將相同的數加起來的快捷方式。(呵呵呵)
逆元素:指一個能夠取消另外一給定元素運算的元素,在數學里,逆元素廣義化了加法中的加法逆元和乘法中的倒數。(???)
乘法逆元:群G中任意一個元素a,都在G中有惟一的逆元a‘,具備性質aa’=a’a=e,其中e為群的單位元。(!!!)編程
咳咳,是否是以為最后兩個很高深?其實第二個不用管,你只須要知道第3個,你能夠這樣理解:
有一個數a,一個模數M,當svg
gcd(a,M)=1(就是a,M互質)g
c
d
(
a
,
M
)
=
1
(
就
是
a
,
M
互
質
)
知足時有
ab≡1(modM)a
b
≡
1
(
m
o
d
M
)
此時b稱為a的乘法逆元,同時此時a也為b的乘法逆元.又能夠說此時a,b互為乘法逆元.
那么此時咱們就能夠表示出:
a≡b?1≡1b(modM)a
≡
b
?
1
≡
1
b
(
m
o
d
M
)
能夠簡單、寬泛地甚至有點錯誤地理解為
分數能夠參加同余運算?
是否是思路清晰了不少(然并卵…)好吧,咱們來舉個例子:
當a=4,M=7時,此時4,7互質,那咱們湊一湊就能夠湊出: 4*2≡1(mod 7),呀!一組乘法逆元就出現了!此時4,2就互為乘法逆元.(hhh…)再來倆例子:
當a=5,M=8時,此時5,8互質,那咱們湊一湊又能夠湊出: 5*5≡1(mod 8),呀!一組乘法逆元又出現了!此時5,5就互為乘法逆元.atom
當a=10,M=3時,此時10,3互質,那咱們湊一湊又能夠湊出: 10*1≡1(mod 3),呀!一組乘法逆元又出現了!此時10,1就互為乘法逆元.spa
咱們能夠發現,在同一M下當gcd(a,M)=1時可能有許多b知足ab≡1(mod M)好比第一個例子 4*2≡1(mod 7),同時4*9≡1(mod 7),4*16≡1(mod 7),說明同一a可能與多個b互為乘法逆元.
好吧,如今對乘法逆元大概了解一丟丟了吧?
補充一下,這里的b咱們又能夠記做inv(a).net
費馬小定理
至于怎么證實的,呵呵,做者并不知道,貌似是跟剩余系有關,有興趣的盆友們本身查查吧,它的內容是:
假如p是質數,且code
gcd(a,p)=1g
c
d
(
a
,
p
)
=
1
那么
ap≡a(modp)a
p
≡
a
(
m
o
d
p
)
ap?1≡1(modp)a
p
?
1
≡
1
(
m
o
d
p
)
好吧,咱們來試一試:
當a=8,p=3時gcd(8,3)=1,因此8^2≡1(mod 3)
當a=5,p=2時gcd(5,2)=1,因此5^1≡1(mod 2)
當a=4,p=5時gcd(4,9)=1,因此4^4≡1(mod 5)
…咱們就默認它是對的吧…
乘法逆元(編程計算)
那么,今天最重要的來了
當有a,M知足gcd(a,M)=1,咱們根據費馬小定理能夠獲得:
orm
aM?1≡1(modM)a
M
?
1
≡
1
(
m
o
d
M
)
那么變一下形:
a?aM?2≡1(modM)a
?
a
M
?
2
≡
1
(
m
o
d
M
)
這個東西是否是知足上面的乘法逆元定義?
因此,此時
a與a^(M-2)互為乘法逆元
那么
aM?2≡a?1≡1a(modM)a
M
?
2
≡
a
?
1
≡
1
a
(
m
o
d
M
)
咱們有知道模運算有乘法結合律
ba≡b?a?1≡b?aM?2(modM)b
a
≡
b
?
a
?
1
≡
b
?
a
M
?
2
(
m
o
d
M
)
這說明,
若是當分數形如b/a(a!=0且為整數)參加模運算時,且gcd(a,M)=1,那么b/a就同余b*a^(M-2)
一個分數轉化成了整數,神不神奇??
因此,
在gcd(a,M)=1時,除以a等價于乘a的乘法逆元
有關乘法逆元題目
這是個人另外一篇博客….題目大意和跟乘法逆元沒有關系的部分(是關于計數方面問題)先在里面看了吧(好吧,我這個可愛的人在刷閱讀量)
…………………………………..
好了,相信你已經看到了這道題組合計數長這個樣子:
xml
(∑i=b+1WC(H?a+i?2,i?1)?C(W+a?i?1,a?1))%MOD(
∑
i
=
b
+
1
W
C
(
H
?
a
+
i
?
2
,
i
?
1
)
?
C
(
W
+
a
?
i
?
1
,
a
?
1
)
)
%
M
O
D
什么,你看不懂?那這種你看得懂了吧?
for(int i=b+1;i<=w;i++)//推導計數方法
ans=(ans+C(h-a+i-2,i-1)*C(a+w-i-1,a-1)%MOD)%MOD;
好了,最重要的問題來了,C(m,n)怎么算??
咱們知道,當m,n很小時,咱們能夠直接硬算.But,這里H,W都是100000級別的數,這樣作確定會TLE的,因而咱們就要預處理:
咱們知道C(m,n)是這樣算的:
blog
C(m,n)=m!n!(m?n)!C
(
m
,
n
)
=
m
!
n
!
(
m
?
n
)
!
看到沒有?階乘!因而咱們能夠把階乘s[i]都給,把組合上半部分預處理出來:
for(int i=1;i<=2*MAXN;i++) s[i]=s[i-1]*i%MOD;
這里為何是2*MAXN?你看看咱們的計數式子就知道了
問題是組合下半部分怎么搞??咱們知道,模運算中遇到除法是不能直接除的,由于有模數MOD但咱們是否是能夠變造成這樣?
C(m,n)=(m!1n!(m?n)!)%MODC
(
m
,
n
)
=
(
m
!
1
n
!
(
m
?
n
)
!
)
%
M
O
D
這里MOD是10^9+7,套路質數,因此知足以前所講的乘法逆元,直接變造成:
C(m,n)=(m!(n!)MOD?2(m?n)!MOD?2)%MODC
(
m
,
n
)
=
(
m
!
(
n
!
)
M
O
D
?
2
(
m
?
n
)
!
M
O
D
?
2
)
%
M
O
D
咱們就能夠把最大的一個inv[i]和最小的inv[0]預處理出來,固然,能夠加一個快速冪:
LL QuPow(LL x,LL y){//快速冪
LL ret=1;
while(y){
if(y&1) ret=ret*x%MOD;
x=x*x%MOD;
y>>=1;
}
return ret;
}
inv[0]=1;
inv[2*MAXN]=QuPow(s[2*MAXN],MOD-2);
好了,那么其實你知道了除以最大s[i]怎么轉換,就能知道剩下的全部:
1si+1≡invi+1≡1si?(i+1)(modMOD)1
s
i
+
1
≡
i
n
v
i
+
1
≡
1
s
i
?
(
i
+
1
)
(
m
o
d
M
O
D
)
你把最右邊的(i+1)乘到第二個上面不就變成了s[i]的乘法逆元?
因此:
1si≡(i+1)?invi+1(modMOD)1
s
i
≡
(
i
+
1
)
?
i
n
v
i
+
1
(
m
o
d
M
O
D
)
那咱們就能夠寫遞推式了:
for(int i=2*MAXN-1;i>=1;i--)
inv[i]=inv[i+1]*(i+1)%MOD;
好了,這處理完了算C(m,n)就簡單了:
LL C(LL m,LL n){//計算排列
return s[m]*inv[n]%MOD*inv[m-n]%MOD;
}
是否是很神奇?
牢記一句話:在gcd(a,M)=1時,除以a等價于乘a的乘法逆元
代碼本身跳回去看吧,順便點個贊我是最喜歡的~~~
(AtCoder - 1974)いろはちゃんとマス目 / Iroha and a Grid(乘法逆元+組合計數)
總結
以上是生活随笔為你收集整理的大数求乘法逆元c语言,乘法逆元(编程计算)+两道版题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu运行android stud
- 下一篇: 3步即可完成在线压缩gif文件大小