乘法逆元

先來看幾個同餘式:
1.(a+b)%p=(a%p+b%p)%p;
2. (a-b)%p=(a%p-b%p)%p;
3. (ab)%p=(a%pb%p)%p;
然而當變成除法的時候同餘式便不對了即:(a/b)%p不等於(a%p/b%p)%p想要解決這個問題我們就可以把除法變成乘法,即變成(a%p*(1/b)%p)%p這樣就正確了,那麼這裏%p情況下的1/b就是b的逆元。
理解了什麼是逆元,那麼就要解決怎麼求逆元。
根據定義可得:(b*(b的逆元))%p==1,我們很快就可以聯想到另一個式子費馬小定理:當a與p互質時,a^(p-1)==1(%p),那麼
a^(p-2)==1/a(%p),那麼一個數a在模p情況下的逆元其實就是pow(a,p-2)%p.
代碼:

#include <bits/stdc++.h>//普通乘法逆元(1/a=a^(p-2)%p)
using namespace std;
#define int long long
int n,m;
int ksm(int a,int k){
    int ans=1,cnt=a;
    while(k){
        if(k&1){
            ans=ans*cnt%m;
        }
        cnt=cnt*cnt%m;
        k>>=1;
    }
    return ans%m;
}
signed main(){
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        int t=ksm(i,m-2);
        cout<<t<<endl;
    }
    return 0;
}

還有一種一連串數字模p求逆元的情況存在遞推式。
乘法逆元模板題
具體代碼:

#include <bits/stdc++.h>//線性遞推逆元
using namespace std;
#define ll long long
int n,p; int inv[3000005];//存對應下標逆元
signed main(){
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    scanf("%d %d",&n,&p); inv[1]=1; printf("%d\n",1);
    for(int i=2;i<=n;i++){
        inv[i]=(ll)(p-p/i)*inv[p%i]%p;
        printf("%d\n",inv[i]);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章