逆元打表

连续整数逆元打表1-n

有的时候要打的表是1-(mod-1)的,包含范围内的所有值。

const int maxm=3e6+5;
const int mod=1e9+7;
int inv[maxm];
void init(){
    inv[1]=1;
    for(int i=2;i<maxm;i++){
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    }
}

原理:

逆元打表_第1张图片
注意:因为要保证 i -1 是正整数,因此左右同时加上p,因此最终的式子为inv[i]=(p-p/i)inv[p%i]%p


阶乘逆元打表1!-n!:

const int maxm=3e6+5;
const int mod=1e9+7;
int fac[maxm];
int inv[maxm];
int ppow(int a,int b,int mod){
    a%=mod;
    int ans=1;
    while(b){
        if(b&1){
            ans=ans*a%mod;
        }
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}
void init(){
    fac[0]=fac[1]=1;
    for(int i=2;i<maxm;i++){
        fac[i]=fac[i-1]*i%mod;
    }
    inv[maxm-1]=ppow(fac[maxm-1],mod-2,mod);//计算出最后一个的逆元
    for(int i=maxm-2;i>=0;i--){//从后往前递推
        inv[i]=inv[i+1]*(i+1)%mod;
    }
}

原理:

在这里插入图片描述
因此只需要求出最后一个数的逆元,然后从后往前递推即可求出所有阶乘的逆元

有的题目既要用到普通逆元也要用到阶乘逆元,这时候可以先预处理普通逆元,然后阶乘逆元finv[i]=finv[i-1]*inv[i]%mod,原理和这个类似。


其他

逆元是积性函数,若a*b=c,则inv[a]*inv[b]%mod=inv[c]

你可能感兴趣的:(逆元打表)