[洛谷P3811]【模板】乘法逆元

P3811 【模板】乘法逆元

題意

求1-n全部整數在模p意義下的逆元。c++

分析

逆元

若是x知足\(ax=1(\%p)\)(其中a p是給定的數)那麼稱\(x\)是在\(%p\)意義下\(a\)的逆元算法

A 拓展歐幾里得算法

\[ax=1(\%p)\]
轉換一下也就是
\[ax+py=1\]函數

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int extgcd(int a,int b,int&x,int&y){
    if(b==0){
        x=1;
        y=0;
        return a;
    }
    int g=extgcd(b,a%b,y,x);
    y-=a/b*x;
    return g;
}
int main(){
    int a,b,x,y;
    cin>>a>>b;
    for(int i=1;i<=a;i++){
        extgcd(i,b,x,y);
        cout<<(x%b+b)%b<<endl;
    }
}

得分:48。TLEspa

B 費馬小定理

當p是質數時:
\[a^{p-1}≡1(\%p)\]
將其變形一下即得
\[a*a^{p-2}≡1(\%p)\]code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll qpow(ll a,ll b,ll p){
    ll ans=1;
    while(b){
        if(b%2){
            ans*=a;
            ans%=p;
        }
        a*=a;
        a%=p;
        b>>=1;
    }
    return ans%p;
}
int main(){
    int n,p;
    cin>>n>>p;
    for(int i=1;i<=n;i++){
        cout<<(qpow(i,p-2,p)%p+p)%p<<endl;
    }
}

得分:48。TLEip

B' 歐拉定理

費馬小定理只是歐拉定理的特殊狀況。歐拉定理:
\[a^{\phi(p)}=1(\%p)\]
也就是說\(a^{\phi(p)-1}\)\(a\)\(\%p\)意義下的逆元。
其中\(\phi\)是歐拉函數:小於n的正整數中與n互質的數的數目。
通式:\(\phi(n)=n\Pi_{i=1}^{n}\left(1-\frac{1}{p_i}\right)\)
遞推性質:ci

  1. \(\phi(p)=p-1\) (p是質數)
  2. \(\phi(ab)=\phi(b)\phi(b)\) (a,b互質)
  3. \(\phi(ip)=p\phi(i)\) (i是p的倍數)
    因此能夠用相似線性篩的方法求出歐拉函數表。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll qpow(ll a,ll b,ll p){
    ll ans=1;
    while(b){
        if(b%2){
            ans*=a;
            ans%=p;
        }
        a*=a;
        a%=p;
        b>>=1;
    }
    return ans%p;
}
ll n,p;
ll phi[20000529],prime[2000052],ps;
bool mark[2000052];
void calc(){
    phi[1]=1;
    for(int i=2;i<=p;i++){
        if(!mark[i]){
            prime[++ps]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=ps;j++){
            if(i*prime[j]>p)break;
            mark[i*prime[j]]=1;
            if(i%prime[j]==0){
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }else{
                phi[i*prime[j]]=phi[i]*(prime[j]-1);
            }
        }
    }
}
int main(){
    cin>>n>>p;
    calc();
    for(int i=1;i<=n;i++){
        cout<<(qpow(i,phi[p]-1,p)%p+p)%p<<endl;
    }
}

得分:32。TLEget

C 神奇的遞推式(正解)


\[p=ka+r\]
而後放到\(\%p\)意義下
\[ka+r=0(\%p)\]
兩邊同時乘以\(a^{-1}r^{-1}\)
\[kr^{-1}+a^{-1}=0(\%p)\]
因此
\[a^{-1}=-kr^{-1}=-\left[\frac{p}{a}\right]*(p\%a)^{-1}\]
轉換成代碼就是it

inv[a]=-(p/a)*inv[p%a];

正解代碼

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,p;
int inv[3000000];
int main(){
    scanf("%d%d",&n,&p);
    inv[1]=1;
    printf("1\n");
    for(int i=2;i<=n;i++){
        inv[i]=((-((ll)p/i)*inv[p%i])%p+p)%p;
        printf("%d\n",inv[i]);
    }
}
相關文章
相關標籤/搜索