求逆元的一些方法總結


求逆元問題是數論中一類比較基礎的題目,它常常會與組合數,質數等聯系起來。今天我們就來總結一下求逆元的方法,根據數據范圍不同有三種,接下來就一一介紹。

-------------------------------------------------------------------------------

方法1.通過擴展歐幾里得算法求逆元

這個算法很常見,在這里就不再累述,直接給出代碼。

    1. 求解ax+by=gcd(a,b),亦即ax≡1(mod b)。函數返回值是a,b的最大公約數,而x即a的逆元。 
    2. 注意a, b不能寫反了。
    3. gcd(a, b) > 1時逆不存在
 1 int ex_gcd(int a, int b, int &x, int &y) {
 2     int ret, tmp;
 3     if (b == 0) {
 4         x = 1;
 5         y = 0;
 6         return a;
 7     }
 8     ret = ex_gcd(b, a % b, x, y);
 9     tmp = x;
10     x = y;
11     y = tmp - a / b * y;
12     return ret;
13 }
View Code

方法2.通過快速冪求逆元

由於費馬小定理,a^(p-1)=1(mod p)-->1/a=a^(p-2)(mod p),故a的逆元為a^p-2.注意這個方法要求模的數必須為質數,傳入a和mod-2即可得到結果。

LL quick_inverse(LL n, LL p) {
    LL ret = 1,exponent = p;
    for (LL i = exponent; i; i >>= 1, n = n * n % mod) {
        if (i & 1) {
            ret = ret * n % mod;
        }
    } 
    return ret;
}
View Code

方法3.通過遞推求1~n的逆元

我們可以通過inv[i]=inv[p%i]*(p-p/i)%p遞推得到逆元。適用於n比較小的情況

1 int inv[N];
2 void get_inverse(int n, int p) {
3     inv[1] = 1;
4     for (int i = 2; i <= n; ++i) {
5         inv[i] = (p - p / i) * inv[p % i] % p;
6     }
7 }
View Code

特殊情況.通過遞推求n!

我們可以利用invf[i]=invf[i+1]*(i+1)%p這個公式反遞推得到1!~n!的逆元。

 1 int invf[N], factor[N];
 2 void get_factorial_inverse(int n, int p) {
 3     factor[0] = 1;
 4     for (int i = 1; i <= n; ++i) {
 5         factor[i] = i * factor[i - 1] % p;
 6     }
 7     invf[n] = quick_inverse(factor[n], p);
 8     for (int i = n-1; i >= 0; --i) {
 9         invf[i] = invf[i + 1] * (i + 1) % p;
10     }
11 }
View Code

----------------------------------------------------------------------------------

本來想再寫一篇組合數的,但肯定沒有苟神講得好,所以直接附上鏈接:組合數取模

感覺講得不好,畢竟蒟蒻還不是很能理解里面的內涵,只是總結一下,等用到就不會很無措,大家多多包涵啦。

-END-

 


免責聲明!

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



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