组合
卡特兰数
类括号序列计数问题的方案数都是卡特兰数,其表达式为 \(H_n=\dfrac{2n\choose n}{n+1}\)。
记住前几项是 \(1,1,2,5,14,42...\)
还有几种计算方法,其中第一个式子默认 \(H_0=1\)。
P1641 [SCOI2010] 生成字符串
类似于 \(H_n={2n\choose n}-{2n\choose n-1}\) 的推导,采用翻折路径法可以得到答案是 \({n+m\choose n}-{n+m\choose n+1}\)。
组合数
范德蒙卷积
ABC290F Maximum Diameter
首先树上度数限制必须满足 \(\sum deg_i=2n-2\)。
对于一组 \(\{deg_n\}\) 序列咋一看构造最大直径很难,其实就是最朴素的思想,把所有度数 \(>1\) 的点串起来,然后把度数为 \(1\) 的叶子节点挂上去即可。因为有上述的度数限制,所有必然可以有方案。
于是我们需要枚举一度点的个数 \(k\),此时的直径长度为 \(n-k+1\)。我们选出 \(k\) 个节点当作叶子,再把剩余度数分配给其他所有节点,\(\sum x_i=n-k\),且 \(x_i\ge 2\)。
首先可以凑一个吸收恒等式,把 \(k\) 提取出来。然后内部运用范德蒙卷积即可。
重要公式
- \(\begin{pmatrix}a\\b\end{pmatrix}\) \(\begin{pmatrix}b\\c\end{pmatrix}=\)\(\begin{pmatrix}a\\c\end{pmatrix}\)\(\begin{pmatrix}a-c\\b-c\end{pmatrix}\)
- \(\sum\limits_{i=r}^n\begin{pmatrix}i\\r\end{pmatrix}=\begin{pmatrix}n+1\\r+1\end{pmatrix}\)
- \(\dfrac{a^{\underline{i}}}{b^{\underline{i}}}=\dfrac{\begin{pmatrix}a\\i\end{pmatrix}}{\begin{pmatrix}b\\i\end{pmatrix}}=\dfrac{\begin{pmatrix}b-i\\b-a\end{pmatrix}}{\begin{pmatrix}b\\a\end{pmatrix}}\)
- \((x+y)^n=\sum\limits_{i=0}^{n}\begin{pmatrix}n\\i\end{pmatrix}x^iy^{n-i}\)
- \(k { n\choose k } = n {n-1\choose k-1 }\)
CF660E Different Subsets For All Tuples
思路显然,计算每种子序列的贡献。注意概念,子序列不需要连续。
空子序列,\(m^n\)。
非空子序列,只统计第一次出现的位置。第一维 \(i\) 枚举长度,第二维 \(j\) 枚举结尾位置。结尾位置确定后,就要在前 \(j-1\) 个位置里面确定 \(i-1\) 个位置来填充了。然后在这前 \(j\) 个位置中,非子序列位置,不能出现子序列下一个要出现的数字,因此只能有 \(m-1\) 种选择,剩下的随便填。
观察形式,尝试凑出二项式定理。
先平移坐标,凑成比较齐整的形式,然后交换求和符合将我们不需要的部分提到外面来,对于内部运用二项式定理。
\(O(n\log n)\) 计算即可。
NFLS 笛卡尔树
求 \(\sum\limits_{p \to T} \sum\limits_{u \in T} (rs_u-ls_u)\),其中 \(T\) 为笛卡尔树,且 \(u\) 必须同时拥有左右儿子才累和,\(ls_u,rs_u\) 为排列 \(p\) 中位置编号,\(n \le 10^6\)。
经典笛卡尔树计数,常见套路是设 \(f_n\) 表示 \(n\) 个点的树的个数,然后枚举左右儿子大小组合数分配。
根据二叉搜索树的性质,根节点左右两边的位置编号应该是连续的。所以我们在累加 \(rs_u-ls_u\) 之后,便可以将问题转化为两个子问题了。
设 \(f_n\) 表示 \(n\) 个节点的答案,\(g_n\) 表示 \(n\) 个节点的时候,根节点权值之和。
\(g_n=\sum\limits_{i=1}^ni\times(n-1)!=\dfrac{n(n+1)}{2}\times(n-1)!=\dfrac{(n+1)!}{2}\)
设根节点在序列中的位置为 \(k\),那么左边节点数 \(a=k-1\),右边节点数 \(b=n-k\)。在分治前提计算之下左右两边分别是 \(1-a\) 和 \(1-b\) 的排列,最后加上根节点形成了一个 \(1-n\) 的排列,根节点是 \(1\),剩下就是要给两个排列分别分配权值,方案数是 \(\begin{pmatrix}a+b\\a\end{pmatrix}\)。
注意,只有同时具有左右儿子的时候才产生贡献,所以小心 \(k\) 的枚举上下界。同时注意我们其实是将右边的位置编号全体减小了 \(k\),所以虽然 \(f\) 是内部处理不影响,但是 \(g\) 是左右两边做差,故需要加上偏移量 \(k\),一共要加 \(a! \times b!\) 对,此时求解是 \(O(n^2)\)。
考虑将 \(\begin{pmatrix}a+b\\a\end{pmatrix}\) 写成阶乘形式,放进去,可以作前缀和,复杂度 \(O(n \log n)\)。
卢卡斯定理
公式及证明
- 公式
\(\begin{pmatrix} n\\m \end{pmatrix} \bmod p=\begin{pmatrix} \lfloor n/p\rfloor \\ \lfloor m/p \rfloor \end{pmatrix} \begin{pmatrix} n \bmod p \\ m \bmod p \end{pmatrix} \bmod p\) - 利用 \((a+b)^p\equiv a^p+b^p \bmod p\) 证明即可。
组合数奇偶性
\(\begin{pmatrix} n\\m \end{pmatrix}\) 为奇数,当且仅当 \(n \operatorname{and} m=m\)。
斯特林数
第一类斯特林数
设 \(s(n,m)\) 表示 \(n\) 个不同的元素构成 \(m\) 个圆排列的个数。
递推公式: \(s(n,m)=s(n-1,m-1)+(n-1) \times s(n-1,m)\)
前者表示该元素单独形成一个圆排列,后者表示先生成 \(n-1\) 个元素的再将该元素插入 \(n-1\) 个元素前面的一个空,共 \(n-1\) 种插法。
也可以用 \(\begin{bmatrix}n\\m\end{bmatrix}\) 来表示。
恒等式
上升幂:\(x^{\bar n}=x\times (x+1)\times .. \times (x+n-1)\)
下降幂:\(x^{\underline{n}}=x\times (x-1)\times ...\times (x-n+1)\)
-
\(\sum\limits_{i=1}^n\begin{bmatrix}n\\i\end{bmatrix}=n!\)。用置换环来理解。
-
\(x^{\bar n}=\sum\limits_{i=0}^n \begin{bmatrix}n\\i\end{bmatrix} x^i\),归纳证明即可。
-
\(x^{\underline{n}}=\sum\limits_{i=0}^n(-1)^{n-i} \begin{bmatrix}n\\i\end{bmatrix} x^i\),利用 \(x^{\underline{n}}=(-1)^n(-x)^{\bar{n}}\)。
第二类斯特林数
高维前缀和
类比一维度的前缀和,二维度的前缀和等,现在我们希望在一个高维空间内求前缀和,之前的容斥写法推广到高维太难写了,因为引进高维前缀和,也叫 SOS DP。
我们枚举维度,然后分别对于每一维度做前缀和即可。
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
for(int k=1;k<=p;++k) a[i][j][k]+=a[i-1][j][k];
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
for(int k=1;k<=p;++k) a[i][j][k]+=a[i][j-1][k];
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
for(int k=1;k<=p;++k) a[i][j][k]+=a[i][j][k-1];
时间复杂度 \(O(\sum V_i \prod V_i)\)。
推广到集合角度,时间复杂度 \(O(n2^n)\)。
for(int i=0;i<w;i++)
for(int j=0;j<(1<<w);j++)
if(j&(1<<i))s[j]+=s[j^(1<<i)];
[ARC100E] Or Plus Max
把二进制下标看成集合,or 相当于并集。就是一个对各子集合取最大和次大的操作。
CF165E Compatible Numbers
把二进制下标看成集合,所求的就是补集的子集。
CF1208F Bits And Pieces
这里有一个小技巧,\(x~or~y=x+\overline x~and~y\)。
于是本题也可以这么转化。接着枚举 \(i\),就变成在 \(i<j<k\) 的前提下求 \(\overline a_i~and~a_j~and~a_k\) 的最大值。
我们通过高维前缀和可以预处理 \(f_s\) 表示 \(s \in a_i\) 中的 \(i\) 的最大值与次大值。
然后对于上面的表达式从高位到低位判断,加入处理到了第 \(z\) 位,那么对于当前已经满足要求的集合 \(S\) 先加上 \(2^z\),然后判断 \(f_s\) 中的次大值是否大于 \(i\)。如果大于表示满足,保留新的 \(s\) 继续询问。否则 \(s\) 减去 \(2^z\)。
P9131 [USACO23FEB] Problem Setting P
首先,如果你按照先后关系建图很难做,考虑看成 01 串的包含关系就很清晰了。
这是一个对于子集求和的形式,还是由于可能有多道题目是同一个 \(01\) 串,所以对于一种含 \(i\) 道题目的 01 串,其系数是 \(cnt_i=\sum\limits_{j=1}^i{i\choose j}j!\)。
列出 DP 方程,
如果没有 \(cnt_{sz_s}\) 的系数,我们可以用高维前缀和直接做。有了系数之后,相当于半在线高维前缀和,也就是每求出一个 \(dp_s\) 之后,我们都要对其乘以一个数。
考虑到是从子集求和,那么有 \(|t|<|s|\),我们直接先枚举集合大小,然后按照集合大小分层转移,当前层由之前层的高维前缀和转移而来,而当前层做完之后,每个数乘以相应系数之后,层内来一个高维前缀和即可。

浙公网安备 33010602011771号