文章目录
写在前面
我上次发了一篇题解: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=Ca−1b+Ca−1b−1(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