[模板] Lucas 逆元 快速幂模板

  • 一般情况下,当Mod较小,组合数较大时用Lucas求组合数,当Mod较大组合数较小时用逆元求组合数
/*
逆元定义:x为a的乘法逆元,(b/a) (mod Mod) = (b * x) (mod Mod)
 x表示a的逆元。并且 a*x ≡ 1 (mod Mod )  
 注意:只有当a与Mod互质的时候才存在逆元
以下两种写法都必须要求MOD为素数
*/
typedef long long ll;
const int Mod=110119;
ll invs[Mod+50];
ll fac[Mod+50];
//1 预处理
void initInv(int Mod){
    invs[1]=1;
    for (int i=2;i<Mod;i++)
        invs[i]=invs[Mod%i]*(Mod-Mod/i)%Mod;
}
//2 直接求
ll inv(int a,int mod){
    return(a==1?1:inv(mod%a,mod)*(mod-mod/a)%mod);
} 
//3 inv(x)=x^(mod-2)
ll qPow(ll x,ll n,ll mod){
    ll ret=1;
    while(n){
        if (n&1) ret=(ret*x)%mod;
        x=(x*x)%mod;
        n>>=1;
    }
    return ret; //x^n%mod
}

void initFac(int Mod){
    //n!
    fac[0]=1;
    for(int i=1;i<=Mod;i++){
        fac[i]=fac[i-1]*i%Mod;
    }
}

ll lucas(ll n,ll k,ll mod){
    //C_n^k%mod
    if (n<0 || k<0 || k>n) return 0;
    ll ret=1;
    while(n && k){
        ll np=n%mod,kp=k%mod;
        if (np<kp) return 0;
        ret=(ret*fac[np]%mod)*invs[fac[kp]*fac[np-kp]%mod]%mod;
      //  ret=(ret*fac[np]%mod)*inv(fac[kp]*fac[np-kp]%mod,mod)%mod;
      //  ret=(ret*fac[np]%mod)*qPow(fac[kp]*fac[np-kp]%mod,mod-2,mod)%mod;
        n/=mod; k/=mod;
    }
    return ret;
}

//调用
    //initFac(Mod);
    //initInv(Mod);
    //return lucas(n,m,Mod);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值