乘法逆元3种方法总结[最全]
建議大家可以先去看看這篇博文
(https://www.cnblogs.com/dupengcheng/p/5487362.html)
乘法逆元:ax≡1 (mod p) 這個(gè)等式用中文描述就是 a乘一個(gè)數(shù)x并模p等于1,即 a%p*x%p=res【并非指res等于1】,而是res%p=1;其中的x為滿足范圍還要對(duì)p求模
需知道的是:
若ax≡1 mod f, 則稱a關(guān)于1模f的乘法逆元為x。也可表示為ax≡1(mod f)。
當(dāng)a與f互素時(shí),a關(guān)于模f的乘法逆元有解。如果不互素,則無解。如果f為素?cái)?shù),則從1到f-1的任意數(shù)都與f互素,即在1到f-1之間都恰好有一個(gè)關(guān)于模f的乘法逆元。【百度百科-乘法逆元】
什么是逆元,為什么要求逆元?
計(jì)蒜客某題所表述:
那么了解基本知識(shí)后,我們來求逆元:
求逆元分為兩類:
1.a p 不互質(zhì)時(shí)逆元無解
可用公式實(shí)現(xiàn)相同功能:
證明:
推薦題目:藍(lán)橋杯小數(shù)第n位
2.a p 互質(zhì)時(shí):
逆元的求法主要有三種(按快慢排序):
第一:線性打表遞推法(遞推公式inv[i]=(p-p/i) * inv[p%i]%p)。
第二:擴(kuò)展歐幾里得算法。(詳解)
第三:費(fèi)馬小定理(快速冪qpow(a,p-2,p))。-(最容易理解)
下面我們把每種求法的模板呈上:
例題引入:乘法逆元
Description
這是一道模板題。
給定正整數(shù) n 與 p ,求 1~n 中的所有數(shù)在模 p 意義下的乘法逆元。
Input
一行兩個(gè)正整數(shù) n 與 p
1 ≤ n ≤ 3×106 , n < p < 20000528
p 為質(zhì)數(shù)。
Output
n 行,第 i 行一個(gè)正整數(shù),表示 i 在模 p 意義下的乘法逆元。
Sample Input
Sample Output
1 7 9 10 8 11 2 5 3 4第一:線性打表遞推法(遞推公式inv[i]=(p-p/i)inv[p%i]%p)
時(shí)間對(duì)比:
參考于:(https://blog.csdn.net/xuechen_gemgirl/article/details/80332859)
第二:擴(kuò)展歐幾里得算法
時(shí)間復(fù)雜度:
為什么可以用擴(kuò)展歐幾里得求得逆元?
我們都知道模就是余數(shù),比如12%5=12-5 * 2=2,18%4=18-4*4=2。(/是程序運(yùn)算中的除)可知a%b=a-(a/b)b
那么ax≡1 (mod p)即ax-yp=1.把y寫成+的形式就是ax+py=1,為方便理解下面我們把p寫成b就是ax+by=1。就表示x是a的模b乘法逆元,y是b的模a乘法逆元。然后就可以用擴(kuò)展歐幾里得求了。
摘自上面鏈接(https://www.cnblogs.com/dupengcheng/p/5487362.html,推薦大家先看一遍)
很多人,包括我一直無法理解擴(kuò)展歐幾里得算法,在我看了好多博文后才大概了解。就拿我碰到的來說:
一擴(kuò)展歐幾里得可以求最大公約數(shù)。
二求ax+by=gcd(a,b)的解x,y。逆元就包括其中。
x是a的模b乘法逆元,y是b的模a乘法逆元(即gcd()=1時(shí)的x/y)
現(xiàn)在來講一下擴(kuò)展歐幾里得到底怎么來的:
其實(shí)我覺得大家只要搞懂后面遞歸的x,y怎么求就幾乎沒問題的了。
原式:ax+by=gcd(a,b)
遞歸:bx+(a%b)y^=gcd(a,b) 【x^和 y^就是上一步的x,y】
其中:a%b=a-(a/b)b
帶入后:ay^+b ( x ^ - ( a/b ) y ^ )=gcd(a,b);
再與原式對(duì)比:ax+by=gcd(a,b)
得出:{
x=y^;
x^-(a/b ) y ^=y;
}
這就是遞歸過程中,x和y的由來
而當(dāng)b=0時(shí),有:(遞歸結(jié)束時(shí)){a=gcd(a,b),x=1,y=0}
a1+b0=a=gcd(a,b)
可得出一個(gè)特解a(最大公約數(shù))
這樣就可以得到每?jī)蓚€(gè)相鄰狀態(tài)的x和y的轉(zhuǎn)化了,就可以在求gcd(a,b)的同時(shí)求對(duì)x,y求解
相信對(duì)于擴(kuò)展歐幾里得算法,大家會(huì)有疑問為什么b=0時(shí)x=1;y=0?
其實(shí)當(dāng)達(dá)到遞歸基時(shí),此時(shí)的a就是gcd(最大公約數(shù)),b=0,那么有ax+by=a。
故x必須等于1,y可以取任何正整數(shù)。
我還是有疑問上面說了“x是a的模b乘法逆元,y是b的模a乘法逆元”
大家都統(tǒng)一b=0時(shí)x=1;y=0;。既然y可以取任何正整數(shù)那么我就要換一個(gè)當(dāng)b=0時(shí):x=1;y=1;這個(gè)“x是a的模b乘法逆元,y是b的模a乘法逆元”結(jié)論還是成立的。
還有一點(diǎn)就是建議y取0,如果取其他數(shù)組,由于y增長(zhǎng)較快,可能會(huì)有越界的問題。
#include<bits/stdc++.h> using namespace std; int exgcd(int a,int b,int &x,int &y)//擴(kuò)展歐幾里得算法 {if(b==0){x=1;y=0;return a; //到達(dá)遞歸邊界開始向上一層返回}int r=exgcd(b,a%b,x,y);int temp=y; //把x y變成上一層的y=x-(a/b)*y;x=temp;return r; //得到a b的最大公因數(shù) } //事實(shí)證明還是遞推快 遞推快但是耗空間 int main(void) {int a,p;//p是mod數(shù)int x,y;while(~scanf("%d %d",&a,&p)){for(int i=1;i<=a;i++){exgcd(i,p,x,y);if(x>0)printf("%d\n",x);elseprintf("%d\n",x+p);//確保逆元x為正整數(shù)}}return 0; }第三:費(fèi)馬小定理(快速冪qpow(a,p-2,p))
時(shí)間復(fù)雜度對(duì)比:
為什么可以用費(fèi)馬小定理來求逆元呢?
(前提是a p 互質(zhì))
由費(fèi)馬小定理 ap-1≡1(mod p) , 變形得 a * ap-2≡1(mod p),答案已經(jīng)很明顯了:若a,p互質(zhì),因?yàn)閍 * ap-2≡1(mod p)且a*x≡1(mod p),則逆元x=ap-2(mod p),用快速冪可快速求之。
摘自上面鏈接(https://www.cnblogs.com/dupengcheng/p/5487362.html)
明顯在大量數(shù)據(jù)的時(shí)候遞推打表快,平時(shí)普通問題用另外兩個(gè)比較方便,但是由于本人數(shù)學(xué)知識(shí)薄弱不能給出證明【捂臉】
給個(gè)大佬講解的鏈接:https://blog.csdn.net/guhaiteng/article/details/52123385
總結(jié)
以上是生活随笔為你收集整理的乘法逆元3种方法总结[最全]的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 测试Python是否安装成功—pytho
- 下一篇: sql分组查询group by结合cou