求乘法逆元的幾種方法

(數學渣,下面的文字可能有誤,歡迎指教)
乘法逆元的定義貌似是基於羣給出的,比較簡單地理解,可以說是倒數的概念的推廣。記a的關於模p的逆元爲a^-1,則a^-1滿足aa^-1≡ 1(mod p)

加減乘與模運算的順序交換不會影響結果,但是除法不行。有的題目要求結果mod一個大質數,如果原本的結果中有除法,比如除以a,那就可以乘以a的逆元替代。

在mod p的運算中,a存在乘法逆元當且僅當a與p互質。一般題目給的是一個大質數,所以只要a不是p的倍數,就以求乘法逆元。

目前瞭解到的求法有三種:
1.擴展歐幾里得。aa^-1≡ 1(mod p),可以轉換爲aa^-1 + py = 1,即是擴展歐幾里得所能解的ax + by = gcd(a, b)。最常用的解法。
int x, y;
int extgcd(int a, int b, int &x, int &y)
{
    if (b == 0){
        x = 1;
        y = 0;
        return a;
    }
    int gcd = exgcd(b, a % b, x, y);
    int tmp = x;
    x = y;
    y = tmp - (a/b) * y;
    return gcd;
}

/*
求解ax+by=gcd(a,b),亦即ax≡1(mod b)。函數返回值是a,b的最大公約數,而x即a的逆元。
注意a, b不能寫反了。
*/

2.由費馬小定理a^(p-1)≡ 1(mod p)(p爲素數),稍作變形即是 aa^(p-2)≡ 1(mod p),是不是發現了,a^(p-2)即是a的逆元,這個可以用快速冪來求。

3.網上看到的一個很厲害的o(n)的遞推,求前n個逆元,不知道是怎麼推出來的,但是可以簡單地證明一下正確性(要求所mod p爲素數)。

首先,1的逆元是1,沒什麼疑問。
假設前i個數的逆元已經求出,那麼
i^-1 = (p%i)^-1 * (p - [p/i]) % p。其中[]表示去尾取整。
(p%i)^-1其實就是(p-[p/i]i)^-1,然後我們左右乘以i,
ii^-1 = (p-[p/i]i)^-1 * ((i-1)p + p-[p/i]i) % p,
其實就是ii^-1 = k^-1 * ((i-1)p + k) % p = 0 + 1 = 1,這樣就證完了=。=

//字體真糟糕。。

int[] inv = new int[MAXN];
inv[1] = 1;
for (int i = 2; i<MAXN; i++)
    inv[i] = inv[MOD%i]*(MOD-MOD/i)%MOD;




今天我們來探討逆元在ACM-ICPC競賽中的應用,逆元是一個很重要的概念,必須學會使用它。

 

對於正整數,如果有,那麼把這個同餘方程中的最小正整數解叫做的逆元。

 

逆元一般用擴展歐幾里得算法來求得,如果爲素數,那麼還可以根據費馬小定理得到逆元爲

 

推導過程如下

                            

 

求現在來看一個逆元最常見問題,求如下表達式的值(已知

 

           

 

當然這個經典的問題有很多方法,最常見的就是擴展歐幾里得,如果是素數,還可以用費馬小定理。

 

但是你會發現費馬小定理和擴展歐幾里得算法求逆元是有侷限性的,它們都會要求互素。實際上我們還有一

種通用的求逆元方法,適合所有情況。公式如下

 

          

 

現在我們來證明它,已知,證明步驟如下

 

          

逆元詳解:   http://blog.csdn.net/acdreamers/article/details/8220787
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章