根据公式再加逆元求组合数

根据公式再加逆元求组合数

如果所求的组合数比较大,一般会让你求其模上一个数的值,此时就要用到逆元了。
求c=a/b%m的值。若有数d使得b·d%m=1,则c=(a/b·1)%m=(a/b·b·d)%m=a·d%m
此时就将除法求模转换成了乘法求模,只要找到b关于m的逆元即可。
怎么找?可以用费马小定理(a(p-1)≡1(mod p),a,p互质)即a·a(p-2)≡1(mod p),则ap-2就是a关于p的逆元。
求C(n,m)直接根据公式C(n,m)%m = n!/(m!·(n-m)!)%m = n!·(m!)-1·(n-m)!-1%m
用inv(i)表示i关于p的逆元,令m=p/i,n=p%i。则m·i+n = p ≡ 0 (mod p) --> n ≡ -m·i(mod p) --> n·(n·i)-1 ≡ -m·i·(n·i)-1 --> inv(i) = (p-p/i)·inv(p%i)%p。所以有以下代码,求组合数的模。

void init(){
    fac[1] = inv[1] = fac[0] = inv[0] = 1;
    for(int i=2;i<N;i++)fac[i] = 1ll*fac[i-1]*i%mod;
    for(int i=2;i<N;i++)inv[i] = (mod-mod/i)*1ll*inv[mod%i] % mod;
    for(int i=2;i<N;i++)inv[i] = 1ll*inv[i]*inv[i-1]%mod;
}

int C(int n,int k){
    if(k<0||n<k)return 0;
    return (ll)fac[n]*inv[k]%mod*inv[n-k]%mod;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值