1. 程式人生 > >乘法逆元模板

乘法逆元模板

int ace lose detail view www. 出現 eve 歐拉函數

乘法逆元及其求法

1.乘法逆元定義:在wiki中也叫倒數,當然是% p 後的,其實就是倒數。如果ax≡1(mod p),且gcd(a,p)=1(a與p互質),則稱a關於模p的乘法逆元為x。

在求解除法取模問題(a/b)%m時,我們可以轉化為(a%(bm))/b
但是如果b很大,則會出現爆精度問題,所以我們避免使用除法直接計算。
可以使用逆元將除法轉換為乘法:
假設b存在乘法逆元,即與m互質(充要條件)。設c是b的逆元,即bc1(modm),那麽有a/b=(a/b)1=(a/b)bc=ac(modm)


即,除以一個數取模等於乘以這個數的逆元取模。

  • 逆元求解一般利用擴歐。
  • m為質數的時候直接使用費馬小定理,m非質數使用歐拉函數。
  • m為質數的時候,神奇的線性方法。

2.費馬小定理:假如a是一個整數,p是一個質數,那麽技術分享a的倍數,可以表示為技術分享 如果a不是p的倍數,也可以寫成技術分享

3.拓展歐幾裏得:已知整數a,b,拓展歐幾裏得算法可以在求得a,b的最大公約數的同時,能找到整數x,y(其中一個很可能是負數),使它們滿足貝祖等式技術分享

4.分析乘法逆元:ax≡1 (mod p) 這個等式用中文描述就是 a乘一個數x並模p等於1,即 a%p * x%p = res, res % p=1;看上去就是同余定理的一個簡單等式 - -。那麽問題來了。

5.為什麽可以用擴展歐幾裏得求得逆元?我們知道模就是余數,比如12%5=12-5*2=2,18%4=18-4*4=2 那麽ax ≡ 1(mod p)即 ax - yp =1.把y寫成+的形式就是ax+py=1,為方便理解下面,我們把p寫成b就是ax + by=1。就表示x是a的模b乘法逆元,y是b的模a乘法逆元。然後就可以用歐幾裏得求。

6.乘法逆元有什麽用?做題時如果結果過大一般都會讓你模一個數,確保結果不是很大,而這個數一般是1e9+7,而且這個數又是個素數,加減乘與模運算的順序交換不會影響結果,但是除法不行。有的題目要求結果mod一個大質數,如果原本的結果中有除法,比如除以a,那就可以乘以a的逆元替代。

(除一個數等於乘它的倒數,雖然這裏的逆元不完全是倒數,但可以這麽理解,畢竟乘法逆元就是倒數的擴展)。

拓展歐幾裏得求逆元代碼:【時間復雜度為O(logn)】

技術分享
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

void exgcd(ll a,ll b,ll& d,ll& x,ll& y)
{
    if(!b) { d = a; x = 1; y = 0; }
    else{ exgcd(b, a%b, d, y, x); y -= x*(a/b); }
}

ll inv(ll a, ll p)
{
    ll d, x, y;
    exgcd(a, p, d, x, y);
    return d == 1 ? (x+p)%p : -1;
}

int main()
{
    ll a,p;
    while(1)
    {
        scanf("%lld %lld",&a,&p);
        printf("%lld\n",inv(a,p));
    }
}
拓展歐幾裏得

費馬小定理求逆元代碼:【O(log2N),在幾次測試中,常數似乎較上種方法大】

技術分享
ll power_mod(ll a, ll b, ll mod)
{
    ll ans = 1;
    while (b)
    {
        if (b & 1) 
            ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}
inv2 = power_mod(a, mod - 2, mod);
費馬小定理

當模p不是素數的時候需要用到歐拉定理

歐拉定理求逆元代碼:【O(√n),即求出單個歐拉函數的值

技術分享
int eurler_phi(int n)
{
    int res = n;
    for(int i = 2; i * i <= n; i++){
        if(n % i == 0){
            res = res / i * (i - 1);
            while(n % i == 0) n /= i;
        }
    }
    if(n != 1) res = res / n * (n - 1);
    return res;
}
歐拉定理

參考:乘法逆元小結+ 逆元的幾種求法(擴展歐幾裏得,費馬小定理或歐拉定理,特例,打表等)+ ACM數論之旅6---數論倒數,又稱逆元(我整個人都倒了( ̄﹏ ̄))

乘法逆元模板