求组合数

从 n 个元素中每次取出 m 个不同元素,不管其顺序合成一组,取得的组合的个数称为组合数,记作C(n,m)。

组合数的递推公式:

求组合数有两个公式,第一个为递推公式:

C(n,m) = C(n-1,m-1) + C(n-1,m)

1.从集合的角度来理解该公式:

从n个元素中选取m个元素,将所有情况看做一个集合A,可以将这个集合划分成选第i号元素和不选第i个元素两个集合B、C;

这样划分的话是不重不漏的,也就是说A = B + C;

如果选i号元素,就还剩下m-1个物品,不选的话就剩下m个物品,所以C(n,m) = C(n-1,m-1) + C(n-1,m);

特别的,C(n,0) = 1、C(0,0) = 1,当n<m时,C(n,m) = 0。 

递推公式求组合数需要两重循环,时间复杂度为O(n^2),空间复杂度也为O(n^2)。

2.代码模板:

for (int i = 0; i < N; i++)
    for (int j = 0; j <= i; j++) {
        if (j == 0)q[i][j] = 1;
        else q[i][j] = (q[i - 1][j] + q[i - 1][j - 1]) % mod;
    }

组合数的计算公式:

n与m太大的话,由于空间不足组合数无法使用递推公式求解,此时用到组合数的计算公式:C(n,m) = n! / m!*(n-m)!。

但组合数的增长的速度比较快,一般会要求对结果取模,但是除法无法直接取模 ( a/b != (a%c) / (b%c) ) ,此时需要利用快速幂求逆元:

 快速幂_如何何何的博客-CSDN博客

1.代码模板:

LL quick_pow(LL a, LL b, LL c) {
    LL res = 1;
    while (b) {
        if (b & 1)res = res * a % c;
        a = a * a % c;
        b >>= 1;
    }
    return res;
}

for (int i = 1; i < N; i++) {
    //fact 阶乘
    //infact 阶乘的逆元
    fact[i] = fact[i - 1] * i % mod;
    infact[i] = infact[i - 1] * quick_pow(i, mod - 2, mod) % mod;
}

c[a][b]=fact[a]*infact[b]%mod*infact[a-b]%mod


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值