1. 程式人生 > >逆元詳解(加擴充套件歐幾里得和費馬小定理的證明)

逆元詳解(加擴充套件歐幾里得和費馬小定理的證明)

最近,wyb小朋友老是不好好搞他的資料結構,跑過來問我數學,沒辦法,所以我決定每天發一篇數論的部落格,騙騙流量(以後wyb有不會的就看我部落格,哈哈哈)先從基礎的更起吧。

逆元:

我第一次接觸逆元是在離散數學的代數系統中,對於一種運算滿足(a * a^{-1} = e)\Lambda(a^{-1} * a = e)e為該運算的單位)則稱a^{-1}a的逆元。

逆元在演算法中的運用:

逆元在演算法中主要是為了整數的除法取模,顯然除法是不能直接取模的。但是我們可以轉化一下,因為乘法是可以直接取模的。

a\ /\ b\ mod \ c\ = a\ *\ b^{-1}\ mod \ c所以我們的問題直接轉變成了求b的逆元。

逆元的求法:(此處的逆元是指的模運算的逆元)

1.費馬小定理:

a^{p-1}\ =\ 1(mod\ p)\Leftrightarrow a\ *\ a^{p-2}\ =\ 1(mod\ p)(此處的p為素數)

要證明費馬小定理,首先我們需要證明對於任意的整數a,b,c有一個素數p滿足gcd(c,p)\ =\ 1

,使得ac\ =\ bc(mod\ p)\Rightarrow a\equiv b(mod\ p)

\small ac=bc(mod\ p)\Leftrightarrow(a\ mod\ p)*(c\ mod\ p)\equiv(b\ mod\ p)*(c\ mod\ p)\Leftrightarrow a\equiv b(mod\ p)

對p取模的所有數字為\small [0,p-1],又因為0乘任何數等於0所以剔除0,令a為任意正整數都有\prod_{i=1}^{p-1}ia=!(p-1)(mod\ p)\Leftrightarrow !(p-1)a^{p-1}=!(p-1)(mod\ p)\Leftrightarrow a^{p-1}=1(mod\ p)原式得證

如果p為小素數我們選擇直接暴力,時間複雜度為O(n)

int Fermat_inverse(int a,int mod)
{
    int res = 1;
    for(int i = 1;i < mod - 1;++i) res *= a;
    return res; 
}

如果p為大素數,我們可以用快速冪求解,時間複雜度為O(logn)

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使得ax\ +\ by\ =\ gcd(a,b)

懶得再寫一篇。

t=gcd(a,b),所以a=i*t,b=j*t,顯然存在兩個整數x,y使得i*x+j*y=1\Leftrightarrow a*x+b*y=gcd(a,b)

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不需要為素數)

費馬定理指出:a^{phi[i]}=1(mod\ p)

所以此處模運算的逆元為a^{phi[i]}=1(mod\ p)\Leftrightarrow a*a^{phi[i]-1}=1(mod\ p)\Leftrightarrow a^{-1}=a^{phi[i]-1}

所以只需要打出尤拉表就能O(1)的求出逆元啦。