算法竞赛
🧠求组合数(四种方法)
00 分钟
2023-5-29
2023-11-23
type
status
date
slug
summary
tags
category
icon
password
Email
文章首发于我的个人博客:欢迎大佬们来逛逛

递推(杨辉三角)

对于求一个数字的组合数: 可以分解为这两种形式:
  • :选择当前数
  • :不选择当前数
因此就得到了递推公式:
由于需要用到二重循环,因此此方法适用的范围是: 左右
时间复杂度:

快速幂+乘法逆元

考虑组合数的计算公式:
我们可以直接计算这个式子中的每一项。
费马小定理:如果 是一个质数,并且 互质,则满足:
乘法逆元:如果 都是质数,并且满足同余方程式: ,则称 的乘法逆元,即:

那么我们可以将费马小定理进行转化,得到:
则如果 都是质数, 就是 的乘法逆元。
因此我们要求 的乘法逆元,直接计算 即可

我们规定:
  • 数组为阶乘数组,保存每个数字阶乘意义下的阶乘。
  • 数组为逆元数组,保存每个数组阶乘意义下的逆元。
因此就可以转换为
如何求这个数组的值呢?
  • 对于阶乘来说比较容易。
  • 对于逆元,需要进行转化: ,因此就是
容易得知此方法计算组合数的使用范围大概是: ,其主要限制为 循环和数组空间大小
时间复杂度:

卢卡斯定理

此方法用于非常大的 ,但是 却比较小的计算。
定理:
即计算组合数就可以利用拆分的方法。(就不证明了)
然后注意到 是一个质数,因此 对其取余后,最后的结果一定比
因此就可以对第二个式子进行 快速幂+逆元 的方法,我们知道这个方法的瓶颈是过大的 导致空间不够或者循环过大,通过这种方法缩小后便可以直接使用此方法。
我们便可以利用递归来依次缩小 的值,进而计算部分组合数,最后相乘即可,递归结束的条件是 ,此时返回 1 即可。
注意在计算某个 的时候,我们的两个数组的预处理是到 为止(因为不可能比 还大了)的。
此方法使用范围(大概):
时间复杂度:

高精度组合数

如果我们需要求 而不需要求其模数,我们可以发现这个数字将会变得非常大,因为组合数的增长是非常快的!此时我们必须要采用高精度的方法。
此方法我们仍然需要用到公式:
步骤:
  1. 首先预处理所有 范围内的质数,使用线氏筛。
  1. 然后统计某个数阶乘意义下能够包含质数的个数
    1. 先处理 能够包含某质数的个数
    2. 再处理 能够包含某质数的个数
    3. 再处理 能够包含某质数的个数
    4. 最后一式减去二三两式就处理出了 所包含的某质数的个数
  1. 最后对所有的质数都执行相同的操作,然后用 ,其中 p是质数。
其中 可以表示为:
我们用高精度乘法来维护。

 
 

评论
  • Twikoo
  • Valine