求乘法逆元的幾種方法


(數學渣,下面的文字可能有誤,歡迎指教)
乘法逆元的定義貌似是基於群給出的,比較簡單地理解,可以說是倒數的概念的推廣。記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;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM