计数学习笔记

2026-03-07

1 排列组合原理

1.1 基础计数原理

  • 加法原理:

完成一件事有 \(n\) 类方法,每类方法数为 \(A_i\),则总方法数为 \(\sum A_i\)

  • 乘法原理:

完成一件事有 \(n\) 个步骤,每步方法数为 \(B_i\),则总方法数为 \(\prod B_i\)

1.2 排列与组合

  • 排列数:从 \(n\) 个不同元素中取 \(m\) 个按顺序排列,

\[A_n^m = \frac{n!}{(n-m)!}! \]

  • 组合数:从 \(n\) 个不同元素中取 \(m\) 个不考虑顺序,

\[C_n^m = \frac{n!}{m!(n-m)!} \]

1.3 卢卡斯定理

  • 定理:对于素数 \(p\)

\[C_n^r \bmod p = \prod C_{n_i}^{r_i} \bmod p \]

  • 递归形式:

\[C_n^r \equiv C_{n \bmod p}^{r \bmod p} \cdot C_{\lfloor n/p \rfloor}^{\lfloor r/p \rfloor} \pmod{p} \]

1.4. 容斥原理

  • 用于计算多个集合的并集,避免重复计数

  • 公式:

\[|A \cup B \cup C| = |A| + |B| + |C| - |A\cap B| - |B\cap C| - |C\cap A| + |A\cap B\cap C| \]

1.5. 特殊的排列组合问题

1.5.1 圆排列

  • \(n\) 个元素中取 \(m\) 个排成圆,旋转重合视为相同

  • 公式:

\[\frac{A_n^m}{m} \]

  • 注意:

\(m=n\) 时,圆排列数为 \((n-1)!\)

  • 与环排列区别:

圆排列只考虑旋转,环排列还考虑翻转

1.5.2 有重复元素的全排列

  • 若有 \(k\) 种元素,数量分别为 \(n_1,\dots,n_k\)

  • 公式:

\[\frac{(n_1+\cdots+n_k)!}{n_1! \cdots n_k!} \]

1.5.3 不相邻组合

  • \(n\) 个不同元素中选 \(r\) 个,要求任意两个不相邻

  • 公式:

\[C_{n-r+1}^{r} \]

1.5.4 有重复元素的组合

  • \(n\) 种元素中选 \(r\)

  • 公式:

\[C_{n+r-1}^{r} \]

1.5.5 错位排列

  • \(n\) 个元素重新排列,使得每个元素都不在原来的位置上

  • 递推公式:

\[D_n = (n-1)(D_{n-1}+D_{n-2}) \]

  • 注意:

其中 \(D_1=0, D_2=1\)

  • 通项公式:

\[D_n = n! \sum_{k=0}^n \frac{(-1)^k}{k!} \]

1.5.6 球盒问题

设球 \(n\) 个,盒 \(k\) 个:

是否可空 公式
相同 不同 \(C_{n-1}^{k-1}\)
相同 不同 \(C_{n+k-1}^{k-1}\)
相同 相同 \(P(n,k)\)
相同 相同 \(P(n+k,k)\)
不同 相同 \(S(n,k)\)
不同 相同 \(\sum_{i=1}^k S(n,i)\)
不同 不同 \(k! \cdot S(n,k)\)
不同 不同 \(k^n\)

2 矩阵快速幂

2.1 快速幂

  • 普通快速幂:

计算 \(a^b \bmod p\)
时间复杂度 \(O(\log b)\)
原理:

将指数二进制分解,利用幂的倍增性质

2.2 矩阵乘法

  • 定义:\(C = A \times B\),其中 \(C_{ij} = \sum_k A_{ik} B_{kj}\)
  • 乘法条件:\(A\) 的列数等于 \(B\) 的行数
  • 性质:
    • 不满足交换律,但满足结合律 \((AB)C = A(BC)\)
    • 单位矩阵 \(I\) 相当于数的 1

2.3 矩阵快速幂

  • 将快速幂推广到矩阵,要求矩阵为方阵
  • 模板:定义矩阵结构体,重载乘法,使用快速幂思想计算 \(M^k\)

2.4 应用:线性递推

  • 斐波那契数列 \(F_n = F_{n-1}+F_{n-2}\) 可用矩阵表示:

    \[\begin{bmatrix} F_n & F_{n-1} \end{bmatrix} = \begin{bmatrix} F_{n-1} & F_{n-2} \end{bmatrix} \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix} \]

    初始向量 \([F_1, F_0]\) 乘上转移矩阵的 \(n-1\) 次幂即可得 \([F_n, F_{n-1}]\)

2.5 构造转移矩阵的一般方法

  • 步骤:
  1. 确定状态向量 \(V_{old}\),包含递推所需的所有项以及可能需要的辅助变量
  2. 写出目标向量 \(V_{new}\),它由 \(V_{old}\) 通过递推关系得到
  3. 矩阵的每一列对应 \(V_{new}\) 的一个分量,列中的系数由该分量的表达式给出
  • 常见类型:
  • 线性齐次递推:如 \(f_n = a f_{n-1} + b f_{n-2}\),状态向量取 \([f_{n-1}, f_{n-2}]\)
  • 带常数项:如 \(f_n = f_{n-1} + f_{n-2} + c\),需引入常数 1,状态向量 \([f_{n-1}, f_{n-2}, 1]\)
  • 带多项式:如 \(f_n = f_{n-1} + n^2\),需维护 \(n^2, n, 1\),因为它们之间有递推关系 \((n+1)^2 = n^2 + 2n + 1\)
  • 带前缀和:如同时求 \(S_n = \sum_{i=1}^n f_i\),可将 \(S_{n-1}\) 加入状态,利用 \(S_n = S_{n-1} + f_n\) 构造

2026-03-21

3. 序列计数

在构造长度为 $ n $ 的序列时,我们通常有两种递推思路

3.1 位置挨着放,维护值的状态

核心思想

我们按位置顺序依次填入数字,此时,关注的是已经用了哪些值

状态定义

通常是 $ dp[i][j] $ 表示已经填了前 $ i $ 个位置,且这 $ i $ 个位置中相对大小关系的某种状态

关键点

当插入一个新元素时,由于不知道后续数字的具体大小,我们通常只关心它的相对排名
这种模型下的转移往往依赖于“插入一个数后,有多少个排名比它小”

3.2 值挨着放,维护位置的状态

核心思想

我们按数值大小顺序依次插入数字,此时,关注的是这些数字在最终序列中的位置分布

状态定义

通常用 $ dp[i][j] $ 表示已经插入了前 $ i $ 小的数字,这些数字在序列中形成了 $ j $ 个连续段

关键点

插入最大的数时,它要么新建一个段,要么连接两个已有的段
这种思路是连续段DP的基础

3.3 总结

位置放值

适合限制与位置顺序有关的问题

值放位置

适合限制与数值相邻有关的问题

4. 相对大小计数

原理

在处理排列时,如果我们不关心具体的数值大小,只关心相对大小,那么所有排列在概率意义上是等价的
利用这个性质,我们通常可以建立关于前缀最大值记录的递推

示例

计算长度为 $ n $ 的排列中,前缀最大值恰好有 $ k $ 个的排列数
这其实就是第一类斯特林数的变体

5. 连续段DP

这是处理排列构造问题的一种强大技巧

5.1 核心思想

顺序

数值按顺序依次插入

状态

维护当前已经插入的数字形成的连续段的数量

连续段的定义

在最终的排列中,如果两个位置相邻且它们的数值是连续的,则属于同一个段

5.2 模板与转移

假设我们插入当前最大的数字 $ i $,当前有 $ j $ 个连续段,考虑插入的方式:

5.2.1 新建段

插入的数字独立成段,不与任何已有段相邻

转移:$ dp[i][j] \leftarrow dp[i-1][j-1] \times (\text{可插入的空隙数}) $
通常可插入的空隙数为 $ j $ 或 $ j+1 $,具体取决于是否允许放在两端

5.2.2 合并两个段

插入的数字正好填补了两个已有段之间的空隙,将它们连接成一个段

转移:$ dp[i][j] \leftarrow dp[i-1][j+1] \times (\text{合并的方式数}) $
通常合并方式数为 $ j $

5.2.3 粘附在段的一端

不合并,仅延长

这是很多问题中还会出现的第三种情况:插入的数字紧挨着某个段的一端,但没有连接两个段
转移:$ dp[i][j] \leftarrow dp[i-1][j] \times (2j) $

5.3 特点

连续段之间是有序的

在模板中,我们并不关心段与段之间的具体顺序,只在合并时通过组合数考虑如何选择空隙

适用范围

解决“排列中相邻数差为1的段”、“排列的峰谷数量”、“构造特定结构的排列”等问题

posted @ 2026-03-07 17:40  Sail-With-Dawn  阅读(45)  评论(0)    收藏  举报