组合数学 笔记
组合数学
本文为阅读 OI-Wiki 组合数学 网上博客后的笔记。
式子
帕斯卡定理
组合意义: 从 \(n\) 个里面选 \(m\) 个, 相当于将某一个提出来, 那么选择 \(m\) 个就可以是从剩下那一堆里选 \(m\) 个, 或者选出 \(m - 1\) 个, 还有一个就是提出来那一个。
对称恒等式
组合意义: 从 \(n\) 个里面选 \(m\) 个就相当于留下 \(n - m\) 个。
吸收公式
组合意义: 计算二元组 \((S, x)\) 数量, 满足 \(S\) 是 \(1~n\) 的子集, 并且 \(x \in S\)。
左边就是枚举 \(S\) 的大小, 然后组合数计算个数, 再乘以大小。
右边就是枚举 \(x\), 再算有多少个集合包含他。
相伴恒等式
组合意义: 就是上面的二元组换成 \((S, x)\), \(x \notin S\)。
上指标求和
组合意义: 从 \(n + 1\) 个里面选出 \(m + 1\) 个就等于我钦定编号最大为 \(k\), 然后枚举每个编号, 在组合数选一下。
组合意义: 和上面差不多, 就是从选出的里面钦定一个特殊的。
交错和
范德蒙德卷积
特殊形式:
组合意义: 从 \(n + m\) 里面选 \(k\) 个就等于我枚举从 \(n\) 个里面选 \(i\), 从 \(m\) 个里面选 \(k - i\), 再乘起来。
上指标卷积
三项式系数恒等式
二项式定理
二项式定理
广义二项式定理
不知道叫啥1
不知道叫啥2
二项式反演
设 \(f_n\) 为恰好选出 \(n\) 个数构成特定结构的方案数, \(g_n\) 为从 \(n\) 个数中选出 \(i \geq 0\) 的构成特定结构的方案数, 显然有:
因为你要选出 \(i\) 个数嘛, 然后就有 \(\begin{pmatrix} n \\ i\end{pmatrix}\) 种选法。
考虑用 \(g\) 推出 \(f\) 那么就有:
若 $$f_m = \sum_{i = m}^{n}\begin{pmatrix} i \ m \end{pmatrix}g_i$$
那么有 $$g_m = \sum_{i = m}^{n} (-1)^{i - m} \begin{pmatrix} i \ m \end{pmatrix}f_i$$
由 \(g\) 推出 \(f\) 的过程, 就叫二项式反演。
例题
[bzoj2839]集合计数
我们设答案为 \(f_i\), 那么我们可以钦定 \(i\) 个必选, 那么剩下的随便选, 就是 \(\large g_i = \dbinom {n}{i} (2^{2^{n - i}} - 1)\)。 考虑这样会算重, 但是刚好会将 \(f_j\) 算重 \(\dbinom {j}{i}\) 次, 所以直接二项式反演即可。
[bzoj3622]已经没有什么好害怕的了
考虑 DP 的话很难办, 但是状态应该是比较好想, 只是转移没法, 我们考虑 \(dp[i][j]\) 表示考虑前 \(i\) 个恰好 \(j\) 个很难办, 我们可以想前面那道题一样钦定 \(j\) 对, 然后算重的, 考虑恰好的个数就是 \(g_i\), 那么就有 \(f_i = \sum_{j = i}^{n} \dbinom {j}{i} g_j\)
CF997C Sky Full of Stars
那么直接拿dp数组二项式反演即可。
Lucas 定理
当模数 \(p\) 小于 \(max(m, n - m)\) 时, \(n!\left( m-n\right) !\)就没有逆元, 所以我们需要用 Lucas 定理, 所以 Lucas 定理并不是用来加速的。
还有一种理解就是, Lucas定理的含义就是将 \(n, m\) 按 \(p\) 进制分解后每一位组合数的和。
反演
实际上就是矩阵乘法。
说白了就是求 \(A\) 的逆矩阵。
第二类斯特林数 行
定义 \(\begin{Bmatrix} n \\ k \end{Bmatrix}\) 表示将 \(n\) 个两两不同的元素,划分为 \(k\) 个互不区分的非空子集的方案数。
递推式
证明: 考虑放入一个数, 如果这个数单独一个子集就是 \(\begin{Bmatrix}n - 1 \\ k - 1\end{Bmatrix}\), 如果在某个子集内就是 \(k\begin{Bmatrix}n - 1 \\ k\end{Bmatrix}\)。 根据加法原理加起来即可。
通项公式
证明: 我们设 \(f_i\) 是把 \(n\) 个两两不同的元素分恰好分到 \(i\) 个到要区分的非空子集的方案数, \(g_i\) 和前者一样, 只是可以有空集。
显然有 $$g_i = 2^i$$
显然有:
然后二项式反演得:
考虑我们的 \(\begin{Bmatrix} n \\ i \end{Bmatrix}\) 为分到不区分的子集, 我们除个序即可。
则:
minmax容斥
min 同理。
证明就是考虑每一个数的贡献, 即可。
例题
P4707 重返现世
也就是求 \(E(max_{n - k} t_i)\)
\(E(max_k t_i) = E(\sum_{T \subseteq S} (-1)^{|T| - k} \dbinom{|T| - 1}{k - 1} min T)\)
考虑期望的运算, 我们可以把系数都提出来就是 \(\sum_{T \subseteq S} (-1)^{|T| - k} \dbinom{|T| - 1}{k - 1}E(min T)\)
我们考虑抽象一下, 也就是我们第一次选数选到这个集合 \(T\) 的期望时间, 也就是 \(\frac{1}{\sum p}\)
那么我们就是考虑算, 硬算的话太慢, 观察数据范围, \(\sum p\) 只有 1e4 中取值, 我们可以搞出每个 \(\sum p\) 的系数, 那么就可以 \(O(m)\) 算了。
考虑算系数的话想一想 DP, 我们设 \(dp[i][j]\) 表示考虑前 \(i\) 位, \(\sum p\) 等于 \(j\) 时的系数和, 我们考虑新加一个数 \((-1)^{|T| - 1}\) 好搞, 就是 \(\dbinom {|T| - 1}{k - k}\) 不好搞, 但是观察数据范围, \(k\) 很小, 我们可以新开一个状态, 用帕斯卡定理即可。
Prüfer序列
这个东西可以所有的有标号的树一一映射到一个一个序列, 也就是一个prufer序列唯一对应一棵有标号的树。
生成prufer序列
每次选择一个编号最小的叶结点并删掉它,然后在序列中记录下它连接到的那个结点。重复 n-2 次后就只剩下两个结点。
还原树
我们定义一个叶子节点有序集合, 每次将prufer序列队头连向叶子节点集合队头, 当prufer序列中某中相同元素全部被弹出时, 说明他的儿子全部被连向了他, 他就成为了一个叶子, 加入叶子集合。
性质
通过prufer序列我们可以知道 \(n\) 个点可以生成的不同有标号无根树的数量是:
- 在构造完 Prüfer 序列后原树中会剩下两个结点,其中一个一定是编号最大的点 n。
- 每个结点在序列中出现的次数是其度数减 1。(没有出现的就是叶结点)
拓展
一个 \(n\) 个点 \(m\) 条边的带标号无向图有 \(k\) 个连通块。我们希望添加 \(k-1\) 条边使得整个图连通。求方案数。
我们考虑这样一个简化的问题: 有 \(k\) 个点, 每个点有 \(d_i\) 的度数限制, 有标号生成树的个数为多少?
考虑prufer序列的性质二, 也就是某个度数为 \(d_i\) 的节点只能在 prufer序列中出现 \(d_i - 1\) 次, 所以个数就是:
然后加上连通块的条件, 如果我们确定了度数, 那么就还要乘上 \(\prod s_i^{d_i}\), 显然我们要枚举所有的度数情况, 化简一下式子发现我们可以用多项式定理, 最后的式子就是: