【C++】 排列与组合算法详解(进阶篇)

本文介绍了几种优化的组合与排列计算算法,包括朴素算法、递推预处理、使用阶乘逆元以及应用Lucas定理的方法。每种算法的时间复杂度不同,适用于不同规模的数据,如递推预处理适用于中小规模数据,而Lucas定理能处理大规模数据。文章鼓励读者尝试优化预处理阶乘逆元的算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

f4e0159841ab450d861dde9e8fb5ba0d.gif

写在前面

我上次发了一篇题解:C++排列与组合算法详解
最开始,我是抱着水题解的想法写的,但却成为了阅读量 最高 的文章,没有之一。

所以今天咱们来重制一篇文章,介绍几个进阶优化版的算法。


算法1:朴素算法

思路

具体见 C++排列与组合算法详解

缺点

不能将结果取模,因为朴素的组合公式在取模意义下没用。


算法2:递推预处理

思路

我们发现:
C a 0 = 1 C a b = C a − 1 b + C a − 1 b − 1 ( a , b > 0 ) C_a^0 = 1\\ C_a^b=C_{a-1}^b+C_{a-1}^{b-1}(a,b>0) Ca0=1Cab=Ca1b+Ca1b1(a,b>0)

所以我们可以写一个递推函数(部分非主要内容已省略):

void init_C()
{
   
    for (int i = 0; i < N; i ++ ) // N 表示预处理最大的下标
        for (int j = 0; j <= i; j ++ )
            if (!j) c[i][j] = 1;
            else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % P;
}

再预处理阶乘:

void f(int n)
{
   
    f[0] = 1;
    for (int i = 1; i <= n; i ++ )
        f[i] = (LL)f[i - 1] * i % P;
}

需要排列的话还可以预处理排列:

void init_A(int n)
{
   
    for (int i = 0; i <= n; i ++ )
        for (int j = 0; j <= i; j ++ )
            a[i][j] = (LL)f[i - j] * c
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星河依旧长明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值