逆元詳解(加擴充套件歐幾里得和費馬小定理的證明)
阿新 • • 發佈:2018-12-24
最近,wyb小朋友老是不好好搞他的資料結構,跑過來問我數學,沒辦法,所以我決定每天發一篇數論的部落格,騙騙流量(以後wyb有不會的就看我部落格,哈哈哈)先從基礎的更起吧。
逆元:
我第一次接觸逆元是在離散數學的代數系統中,對於一種運算滿足(為該運算的單位)則稱是的逆元。
逆元在演算法中的運用:
逆元在演算法中主要是為了整數的除法取模,顯然除法是不能直接取模的。但是我們可以轉化一下,因為乘法是可以直接取模的。
所以我們的問題直接轉變成了求b的逆元。
逆元的求法:(此處的逆元是指的模運算的逆元)
1.費馬小定理:
(此處的p為素數)
要證明費馬小定理,首先我們需要證明對於任意的整數a,b,c有一個素數p滿足
對p取模的所有數字為,又因為0乘任何數等於0所以剔除0,令a為任意正整數都有原式得證
如果p為小素數我們選擇直接暴力,時間複雜度為:
int Fermat_inverse(int a,int mod)
{
int res = 1;
for(int i = 1;i < mod - 1;++i) res *= a;
return res;
}
如果p為大素數,我們可以用快速冪求解,時間複雜度為:
long long fast_pow_mod(long long a,long long b,long long mod) { long long res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1; } return res; } long long Fermat_inverse(long long a,long long mod) { return fast_pow_mod(a,mod - 2,mod); }
2.擴充套件歐幾里得:
對於任意的兩個正整數(負整數將負號提至係數)a,b必然存在兩個整數x,y使得
懶得再寫一篇。
設,所以顯然存在兩個整數x,y使得
int extend_gcd(int a,int b,int &x,int &y)
{
if(!b){
x = 1,y = 0;
return a;
}
else{
int t = extend_gcd(b,a % b,y,x)
y -= (a / b) * x;
return t;
}
}
至於取逆元:
int inverse_extend_gcd(int n) { int x,y; gcd_plus(n,mod,x,y); x = (x % mod + mod) % mod; return x; }
當然,擴歐求逆元和費馬小定理求逆元有一個相同的問題,那就是,對於此處的mod要求必須得是素數!!!
3.尤拉表求逆元(mod不需要為素數)
費馬定理指出:
所以此處模運算的逆元為
所以只需要打出尤拉表就能的求出逆元啦。