组合数求法

方法1:逆元求法

要求MOD是质数
void work() {    
    inv[1] = 1;
    for (int i = 2; i < N; ++i) 
        inv[i] = (MOD - MOD / i)* inv[MOD%i] % MOD;//逆元(原理见下图)
    f[0] = finv[0] = 1;
    for (int i = 1; i < N; ++i) {
        f[i] = f[i-1] * i % MOD;//阶乘
        finv[i] = finv[i-1] * inv[i] % MOD;//阶乘的逆元
    }
}

在这里插入图片描述
在这里插入图片描述

方法2:杨辉三角

C n m \textrm{C}_{n}^{m} Cnm = C n n − m \textrm{C}_{n}^{n-m} Cnnm = C n − 1 m − 1 \textrm{C}_{n-1}^{m-1} Cn1m1 + C n − 1 m \textrm{C}_{n-1}^{m} Cn1m

只适合n,m都比较小的情况
for (int i = 0; i < N; ++i) {
    a[i][i] = a[i][0] = 1;
    for (int j = 1; j < i; ++j) 
        a[i][j] = (a[i-1][j] + a[i-1][j-1])%mod
}

在这里插入图片描述

方法3:费马小定理

C n m \textrm{C}_{n}^{m} Cnm = n ! m ! ( n − m ) ! \frac{n!}{m!(n-m)!} m!(nm)!n!

费马小定理: b b b ( p − 1 ) ^{(p-1)} (p1) ≡ 1 ( m o d p ) (mod p) (modp)

ll inv(ll x){ return x==1 ? 1 : (mod-mod/x)*inv(mod%x)%mod;}//求逆元
ll C(ll n,ll m){
    if(m < 0 || n < m) return 0;//特判
    if(m > n-m) m = n-m;//性质的转换
    ll zi = 1, mu = 1;//分子和分母
    for(ll i = 0; i < m; i++){
        zi = zi * (n-i) % mod;//分子做 n-m+1 ~n 即n!与(n-m)!约掉
        mu = mu * (i+1) % mod;//分母做m的阶乘
    }
    return zi * inv(mu) % mod;
}

在这里插入图片描述

方法4:Lucas定理

可以优化 m , n m,n m,n都很大的情况,递归解决
C n m \textrm{C}_{n}^{m} Cnm = C m ( m o d ) p n ( m o d ) p \textrm{C}_{m(mod)p}^{n(mod)p} Cm(mod)pn(mod)p * C m / p n / p \textrm{C}_{m/p}^{n/p} Cm/pn/p
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值