dp 与 计数相关

主旋律系列

UOJ #37. [清华集训 2014] 主旋律

[pres] DAG 计数

考虑如何计数 \(n\) 个点的有标号 DAG 数量。设 \(f_i\) 表示 \(i\) 个点的有标号 DAG 数量。对于 DAG,可以每次按照拓扑排序顺序剥去所有入度为 \(0\) 的节点,按照这样的顺序来 dp。

第一个考虑是枚举度数为 \(0\) 的节点集合,但这样需要保证剩的所有点在原图上度数都不为 \(0\),这是困难的。于是考虑容斥,考虑计算“至少保证这个集合内的点度数为 \(0\)”,不难发现点集是什么对答案没有影响。于是有一个枚举子集大小的二项式容斥:

\[f_i=\sum_{j=1}^i(-1)^{j-1}\binom{i}{j}2^{j(i-j)}f_{i-j} \]

正确性是显然的,于是这个问题可以做到 \(O(n^2)\)


接下来考虑这个题:给定一个有向图,问有多少个边集删去后原图仍然强联通。\(n\leq 15\)

不妨计算删去后原图不再强联通的方案数。不再强联通,等价于强联通缩点后形成一个点数 \(>1\) 的 DAG。于是考虑对缩点后的 DAG(也即删边后的强联通分量)进行计数,设 \(h_S\) 表示 \(S\) 这个强联通分量集合做成 DAG(不一定满足点数 \(>1\))的方案数,有:

\[h_S=\sum_{T\subset S}(-1)^{|S-T|-1}2^{edge_{S-T,T}}h_T \]

你发现我们的容斥系数和强联通分量集合大小的奇偶性有关。于是不妨设 \(f_S\) 表示原始点集 \(S\) 在删边后恰好形成奇数个强连通分量的方案数,\(g_S\) 表示偶数个强联通分量的方案数,\(dp_S\) 表示 \(S\) 被划分成 \(>1\) 的 DAG(也即不强联通)的方案数,类比上式可得

\[dp_S=\sum_{T\subset S}(f_{S-T}-g_{S-T})2^{edge_{S-T,T}}\times 2^{edge_{T,T}} \]

注意到这个位置,\(dp\) 有点数 \(>1\) 的限制,因此 \(T\) 为空集时的 \(f\) 中,强联通分量恰好为 \(1\) 的那一部分不能被计入。下面会具体描述这个部分带来的细节。

最后乘上边的全集是因为,无论如何选,\(T\) 的导出子图都能被缩成 DAG,而我们不需要它的数量 \(>1\),故不选用 \(dp\) 值来进行转移。

最后考虑 \(f\)\(g\) 的计算方式。不妨设 \(ans_S\) 表示集合 \(S\) 强联通的方案数,有 \(f_S=\sum_{T\subseteq S , lowbit(S)\in T}ans_T\times g_{S-T}\)\(g\) 数组转移同理。注意到此处需要用到 \(ans_S\) 的值来转移 \(f\)\(g\),然而 \(dp_S\) 又需要 \(f_S,g_S\) 来进行转移。注意到对于 \(g\) 而言,\(f_{\phi}=0\),故实际上不需要 \(ans_S\) 来求得实际值;对于 \(f\) 而言,\(g_{\phi}=0\),此时对应的贡献为形成 \(1\) 个强联通分量的部分,恰好是上述提到的,不能被计入的部分!于是在求 \(dp\)\(ans\) 之前先求出 \(f\)\(g\),再将 \(f\) 的值补上即可。

具体地,设 \(f_S\) 表示 \(S\) 形成强联通分量的方案数;\(g_S\) 表示 \(S\) 形成若干个之间没有边的强联通分量的带容斥系数方案数和。\(f\) 可以枚举一个非空子集表示其为钦定的缩点后形成的 DAG 的入度,其他任意,进行容斥;\(g\) 枚举 lowbit 所在的强联通分量进行合并。仍然存在相互转移的问题,但 \(f_S\) 转移时不能利用 \(g_S\) 中恰好一个的方案,于是先转移完所有 \(g_S\) 里不含单个 \(S\) 的方案,利用它转移给 \(f\),再把这个 \(f\) 补进 \(g\) 即可。

复杂度瓶颈在于 \(3^n\) 的枚举子集中,每次都要计算两个点集之间的边数,复杂度为 \(O(3^nn^2)\)。如果将每个点集的出边和入边压进 bitset,则可以在 \(O(3^n\frac {n^2}{w})\) 的复杂度内解决该题。

最后发现好像也不需要分奇偶性做两个 dp,记录一个带容斥系数的 dp 就可以了。

P10221 [省选联考 2024] 重塑时光

首先不难发现这个神奇的插入过程与一个 \((n+k)\) 的排列一一对应。于是我们可以转为求合法排列数,最后除掉 \((n+k)!\)

考虑裁剪操作。问题变为要把一个 DAG 划分成若干块,使得块间存在拓扑序,一种方案的权值是每一块的内部拓扑序数量乘积,问权值和。不难发现求出这个后,后续处理最后剪成的段数密切相关,因此考虑对每一个段数 \(x\) 算答案。对于一个块数 \(x\),我们插入 \(k\) 个加点操作,要求前后可以有,中间必须有,转为在 \(k\) 个操作中插入块即可知道方案数系数为 \(x!k!\binom{k+1}x\)。于是只需要算每一个 \(x\) 的权值和。

这种 DAG 构成的 dp,考虑钦定某些块入度为 \(0\) 做容斥。设 \(f_{S,i}\) 表示 \(S\) 集合内划分成 \(i\) 块满足条件的权值和,\(g_{S,i}\) 表示 \(S\) 集合内划分成 \(i\) 个块,且块之间不存在连边的权值和,\(h_S\) 表示 \(S\) 的拓扑序数。预处理一个点到一个路径是否可达即可类似地完成转移。注意算 \(f\) 时,由于“入度”的概念是对于块而非点产生的,故容斥系数的幂次上应当是块数而非点数。此时复杂度是 \(f\) 的卷积,为 \(O(3^nn^2)\)

然后有一些优化。考虑利用 OGF 优化卷积运算,令 \(f,g\) 为多项式的系数,那么可以把转移写成多项式形式:\(F_S=\sum_{T\subseteq S}G_TF_{S-T}\)。显然一个多项式的次数不超过 \(n\),而我们想要求的是 \(F_N\) 的系数。于是我们考虑给每个多项式分别带入 \(1\sim n+1\) 的点值,直接利用定义算出 \(G_T\) 的每一个值;然后 \(F\) 的点值可以直接用多项式形式递推,单个点值复杂度是 \(O(3^n)\),因此总复杂度为 \(O(3^nn)\)。最后利用点值还原多项式系数即可。

P11834 [省选联考 2025] 岁月

又考了一次主旋律。待补。

希望大家一直记得我。

杂题

QOJ9128. Priority Queue 3

题意:给定一个初始为空的小根堆和一个长为 \(n+m\) 的操作序列,其中含有 \(n\)+ 操作和 \(m\)- 操作,加操作可以任选一个之前未加入堆的,\([1,n]\) 中的正整数加入堆;减操作需要将堆中最小的元素弹出。给定大小为 \(m\) 的集合 \(A\),问有多少种加入顺序使得最终被弹出来的元素集合等于 \(A\)\(n,m\leq 300\)

不妨找性质。最终被弹出来的元素集合等于 \(A\) 的充要条件是:

  • 任意一次弹出操作执行时,堆中都需要存在一个集合 \(A\) 中的值。
  • 对于任意一个在 \(A\) 中的元素 \(x\),在它被弹出之前,所有满足 \(v\notin A\)\(v<x\) 的元素 \(v\) 都不能被加进堆里去。

正确性是显然的。于是利用这些性质进行 dp,不妨先设 \(x\) 表示到 \(1\sim i-1\) 操作中 + 的数量,\(y\) 表示 - 的数量。根据上述两个条件,容易设计状态 \(f_{i,j,k,0/1}\) 表示考虑到第 \(i\) 个操作,当前未被弹出的最大的 \(A\) 中元素从小到大编号为 \(j\),堆中在 \(A\) 里的元素个数为 \(k\),且 \(A_j\) 是否在堆中的方案数。接下来考虑转移:

  • 对于 + 操作:
    • 加入一个非 \(A\) 中的元素:\(f_{i-1,j,k,l}\times [n-A_j-(m-j)-(x-y-k)]\to f_{i,j,k,l}\)
    • 加入一个 \(A_j\)\(f_{i-1,j,k,0}\to f_{i,j,k+1,1}\)
    • 加入一个小于 \(A_j\)\(A\) 中元素:\(f_{i-1,j,k,l}\times(j-1-(y+k-(m-j)-l))\to f_{i,j,k+1,l}\)
  • 对于 - 操作:
    • \(k>1\)\(k=1,l=0\)\(f_{i-1,j,k,t}\to f_{i,j,k-1,t}\)
    • \(k=1,l=1\),则此时 \(A_j\) 会被弹出,需要找到下一个未被弹出的元素 \(p\),则需要满足 \(p+1\sim j-1\) 在之前被加入过。这个东西现在还不能保证,于是考虑修正一下转移,对于在状态 \(f_{i,j,k,l}\) 下,加入的\(A\) 中且小于 \(j\) 的元素,我们只确定这个事情发生过,但不钦定加入的是哪一个元素,当 \(j\) 被弹出时,再确定 \(p+1\sim j-1\) 的元素在什么时候被加入了。于是转移修正为:
      • + 操作中加入一个小于 \(A_j\)\(A\) 中元素:\(f_{i-1,j,k,l}\to f_{i,j,k+1,l}\)
      • - 操作中 \(k=1,l=1\)\(f_{i-1,j,k,l}\times \binom{y-(m-j)}{j-p-1}\times (j-p-1)!\to f_{i,p,0,0}\)

于是总复杂度 \(O(n^3)\)

CF1437F Emotional Fishermen

题意:给定一个长度为 \(n\)\(a\) 数组,求在所有的 \(n!\) 种重排方式中,有多少种满足对于任意的 \(i\),若 \(1\sim i-1\)\(\max\)\(v\),则要么 \(i\geq 2v\),要么 \(2i\leq v\)

\(a\) 排序,考虑取出前缀 \(\max\) 的点,不难求出 \(pre_i\) 表示最后一个满足 \(2a_j\leq a_i\) 的点 \(j\)。不难发现合法的充要条件:

  • 对于任意一个前缀最大值 \(i\),假设它之前的那个前缀最大值为 \(j\),有 \(a_i\geq 2a_j\),且最终序列内 \(i\) 之前的所有非前缀最大值点在 \(a\) 中的下标一定不超过 \(pre_j\)

考虑往 \(n\) 个位置上填数。注意到上面的第一个限制等价于,对于一个作为前缀最大值的 \(i\),在填完了 \(1\sim pre_j\) 的所有数,并填完了 \(i\) 以前的所有前缀最大值后,\(i\) 应当填在首个空的位置上。也就是说,我们只需要在唯一地填好 \(i\) 之后,确定 \(pre_j+1\sim pre_i\) 之间的非前缀最大值的位置填在哪里即可。

于是可以设 \(f_i\) 表示填了 \(i\),且它是前缀最大值的方案数。枚举上一个前缀最大值 \(j\),此时有 \(j\leq pre_i\)。此时我们需要将 \(pre_j+1\sim pre_i\) 的所有数的位置确定下来。这个区间中的前缀最大值显然只有 \(j\) 一个,也就是说此时被占用的位置数为 \(pre_j+2\)(还有 \(i\) 本身),因此有转移 \(f_i=\sum_{j=0}^{pre_i} f_j\times A_{n-pre_j-2}^{pre_i-pre_j-1}\)。将排列数拆开得到 \(\frac{(n-pre_j-1)!}{(n-pre_i-1)!}\),不妨前缀和维护即可,由于 \(n\) 一定是最后一个前缀最大值,故答案为 \(f_n\)。时间复杂度 \(O(n\log n)\),瓶颈是排序。

???

题意:给一棵 \(n\) 个点的树染成三种颜色,要求任意一个红色的节点子树内红色节点数不超过 \(A\),蓝色的节点的相同限制值为 \(B\),绿色节点为 \(C\),求合法方案数。\(n\leq 500\)

首先朴素的两层背包是 \(O(n^4)\) 的,这就说明我们只能在状态中记录至多一个颜色的数量。

注意到一个性质,对于一个某种颜色的点 \(u\),其子树中所有相同颜色的点都不再需要考虑限制。于是枚举根节点的颜色,并设 \(f_{i,j}\) 表示节点 \(i\) 的父亲到根的路径上节点全部相同,且 \(i\) 子树内有 \(j\) 个点和根颜色相同,另两个颜色满足要求的方案数。处理辅助数组 \(g_{i,j,0/1/2}\) 表示对于某种颜色,考虑到 \(i\) 子树内(不考虑 \(i\)),\(j\) 个点是这个颜色且该颜色合法,其他点不限的方案数(用背包可以简单统计),枚举 \(i\) 点的颜色:

  • \(i\) 颜色和根相同,则直接做背包合并即可,此处没有限制;
  • 否则,根节点对应颜色存在一个限制,枚举其数量,则另一个颜色数量同时确定。该颜色和根节点颜色的方案数可以用组合数直接算;另一个颜色的方案数可以用 \(f\) 直接得到。

复杂度 \(O(n^3)\),瓶颈在算 \(g\) 的时候有一个枚举数量。

P7519 [省选联考 2021 A/B 卷] 滚榜

注意到它是对排列计数,而非是对 \(b\) 计数,所以直接对着 \(b\) 状压,枚举 \(b\) 的取值的计数是不可行的。考虑先暴力枚举排列,判断一个排列是否可行。

对于一个排列 \(p\),我们的限制是 \(a_{p_i}+b_{p_i}\geq a_{p_{i-1}}+b_{p_{i-1}}\)\(b_{p_i}\geq b_{p_{i-1}}\),前式取等的情况需要特殊处理编号关系。不难想到我们让每个位置取合法的最小 \(b\) 一定是最优的,多余的全部放在最后一个即可。也即若 \(a_{p_i}\geq a_{p_{i-1}}\),则 \(b_{p_i}=b_{p_{i-1}}\);否则 \(b_{p_i}=b_{p_{i-1}}-a_{p_i}+a_{p_{i-1}}\),注意特殊处理编号关系,最终需要 \(b\) 的和不超过 \(m\)

于是可以状压,设 \(f_{S,i,j,k}\) 表示已经选定的队伍为 \(S\),最后一个的编号为 \(i\)\(b\) 值为 \(j\),总和为 \(k\) 的排列方案数,复杂度 \(O(2^nn^2m^2)\)。这个状态数显然爆炸,需要优化掉一个 \(m\)。观察上面那个式子并试图去掉记录上一个 \(b\) 的那一维,发现 \(b\) 的增加量只和 \(a\) 有关,于是对每次的增加量计算总贡献,不妨设 \(i-1\to i\) 的增加量为 \(d_i\),则有 \(\sum b_i=\sum_{i=1}^nd_i\times(n-i+1)\)。于是可以直接设 \(f_{S,i,j}\) 表示已经选定的队伍为 \(S\),最后一个的编号为 \(i\),总和为 \(j\) 的方案数。复杂度 \(O(2^nn^2m)\),计算 \(d\) 时注意特殊处理编号关系。

???

题意:考虑对一张 \(n\) 个点的简单图采用 Floyd 算法求 \(f_{i,j}\) 表示 \(i,j\) 两点是否连通,正确算法的最外层循环范围应当是 \([1,n]\),初始时有边相连的两点 \(u,v\) 满足 \(f_{u,v}=1\),同时 \(f_{u,u}=1\)。给定正整数 \(m\in [0,n]\),一个错误算法是将最外层循环范围开到 \([1,n-m]\)。问有多少个 \(n\) 个点的简单图,在运行错误算法后得到的结果仍然正确。\(n\leq 100\),多测,\(T\leq 10^4\)。一个正确的算法代码如下:

for (int k = 1; k <= n; k++) 
    for (int x = 1; x <= n; x++) 
        for (int y = 1; y <= n; y++) 
            f[x][y] |= f[x][k] & f[k][y];

对于 Floyd 算法,最外层循环的变量 \(k\) 表示只途径 \(1\sim k\) 的点,哪些点之间是连通的。若设 \(1\sim n-m\) 的点为黑点,其余点为白点,则合法图中的每一个连通块需要满足下面的条件:

  • 若这个连通块内没有黑点,则他是一个团。
  • 否则,黑点之间需要互相连通,且每个白点都需要与至少一个黑点相连。

考虑先设 \(f_{i,j}\) 表示 \(n=i,m=j\) 的答案,\(m=0\) 时是简单的。对于 \(m>0\),考虑递推求解,考察 \(n\) 所在的连通块情况(注意此时 \(n\) 一定是白点)。

  • \(n\) 所在的连通块内没有黑点,则 \(f_{n,m}\gets \sum_{i=1}^m f_{n-i,m-i}\binom{m-1}{i-1}\)
  • 否则,枚举连通块大小和白点数目,则 \(f_{n,m}\gets\sum_{i=1}^n\sum_{j=1}^{\min(i-1,m)}f_{n-i,m-j}\binom{m-1}{j-1}\binom{n-m}{i-j}g_{i-j,j}\),其中 \(g_{x,y}\) 表示有 \(x\) 个黑点、\(y\) 个白点的合法连通块数目。

考虑计算 \(g\),不妨首先设 \(h_i\) 表示有 \(i\) 个点的简单连通图数目,以此来计算黑点方案数。考虑容斥,用总的减去不连通的,枚举 \(i\) 所在连通块即可。容易推出 \(h\)\(g\) 的式子:

\[\begin{aligned} h_n&=2^{\frac{n(n-1)}{2}}-\sum_{i=1}^{n-1}h_i\times 2^{\frac{(n-i)(n-i-1)}{2}}\times \binom{n-1}{i-1}\\ g_{n,m}&=h_n\times (2^n-1)^m\times 2^{\frac{m(m-1)}{2}} \end{aligned} \]

总复杂度 \(O(n^4)\),瓶颈在枚举连通块大小和白点个数。

???

题意:有 \(n\) 个队参加 2v2 的比赛,当前已经决出了一个冠军,不过自然是小 M 队!现在,小 W 想知道小 M 队的队伍编号,不过小 M 比较菲克,不直接告诉小 W,但是会回答某种形式的问题。具体地,小 W 可以询问一个所有区间的子集 \(S\subseteq \{(l,r)|1\le l\le r\le n\}\)。而小 M 会对于所有 \((l,r)\in S\) 告诉小 W,自己的队伍是否在 \([l,r]\) 中。现在,小 W 想知道,有多少种子集 \(S\),能确定小 M 的队伍编号,对给定模数 \(P\) 取模。\(n\leq 300\)

对于一次询问子集 \(S\),设 \(s_i\) 表示覆盖位置 \(i\) 的区间集合。若存在一个 \(i\neq j\) 使得 \(s_i=s_j\),则不能确定小 M 的队伍编号。

一个关键的性质是,对于任意 \(S\),一定不存在一个 \(a<b<c<d\) 使得 \(s_a=s_c\)\(s_b=s_d\)\(s_a\neq s_b\)。换句话讲,所有相等关系一定是要么包含、要么不交的。我们将最外层的包含段找出,即每次找到最靠右的 \(j\) 使得 \(s_j=s_i\),然后令 \(i=j+1\) 继续寻找。则此时,每一段内部可以任意选取(不包含 \(i,j\) 的),方案数为 \(2^{\frac{(j-i-1)(j-i)}{2}}\)。段间询问区间的左端点必定为某个 \(i\),右端点必定为某个 \(j\),且需要保证不同段的覆盖情况不同。注意到这等价于一个长度为段数的子问题。于是该问题不难解决。

具体地,设 \(f_{i,j}\) 表示长度为 \(i\),分成 \(j\) 段,只考虑选择段内区间的方案数。有 \(f_{i,j}=\sum_{k=0}^{i-1}f_{k,j-1}\times 2^{\frac{(i-k-2)(i-k-1)}{2}}\)。可以 \(O(n^3)\) 求出。再设 \(g_i\) 表示长度为 \(i\) 的答案,通过容斥减去不合法方案,有 \(g_i=2^{\frac{i(i+1)}{2}}-\sum_{j=1}^{i-1}f_{i,j}g_j\)。预处理 \(2\) 的幂次即可做到 \(O(n^3)\)

CF1838E Count Supersequences

不难想到的是能匹配就匹配,于是枚举 \(a_n\) 的匹配位置 \(i\) 得到一个式子:

\[ans=\sum_{i=1}^m \binom{i-1}{n-1}(k-1)^{i-n}k^{m-i} \]

不容易化简,考虑到 \(n\) 有限制,故计算不合法方案数,枚举哪一个是最后匹配的,计算方式与上文类似。这样的好处是,最后一个匹配位置之后的方案数仍然是 \((k-1)\),便于消去内层枚举的幂次,便于化简。注意有一个都不匹配的情况,有:

\[\begin{aligned} ans&=k^m-(k-1)^m-\sum_{i=1}^{n-1}\sum_{j=i}^{m}\binom{j-1}{i-1}(k-1)^{j-i}(k-1)^{m-j}\\ &=k^m-(k-1)^m-\sum_{i=1}^{n-1}(k-1)^{m-i}\sum_{j=i}^m\binom{j-1}{i-1}\\ &=k^m-(k-1)^m-\sum_{i=1}^{n-1}(k-1)^{m-i}\binom mi \end{aligned} \]

QOJ8047.DFS Order 4

题意:设一棵树的唯一 dfs 序为:所有儿子按照编号从小到大顺序访问得到的 dfs 序。对于所有父亲节点小于儿子的 \((n-1)!\) 棵树,求它们有多少种不同的唯一 dfs 序。\(n\leq 800\)

计数题关注一一对应关系、以及一一对应关系导出的计数对象的转换。

考虑怎样的不同树属于同一个等价类,你发现对于一个点,若其同时存在两个相邻儿子 \(u,v\) 满足 \(u<v\),且 \(u\) 的最大儿子 \(x\) 满足 \(x<v\),则将 \(v\) 改接在 \(u\) 下方作为新的最后一个儿子,DFS 序不变;若 \(u\) 为叶子,则也可以把 \(v\) 挂在 \(u\) 下面。于是我们持续进行这样的操作直到不能操作,得到的树满足任意两个相邻兄弟 \(u<v\),都有 \(u\) 存在儿子且其最大儿子 \(x>v\)。对于 DFS 序考察其生成树的过程,不难发现这样的树与唯一 dfs 序是一一对应的。

于是考虑对树计数。首先可以设 \(f_{i,j}\) 表示一棵 \(i\) 个点的树,最后一个儿子的相对编号为 \(j\) 的方案数,考虑扣掉第一个儿子计数,则当根节点仅有一个儿子时有 \(f_{i,2}=\sum_{j=2}^{i-1}f_{i-1,j}\),否则枚举第一个子树的大小 \(k\),有 \(f_{i,j}=\sum_{k=2}^{i-2}\sum_{l=2}^{k}f_{k,l}\times f_{i-k,j}\times(\binom{i-2}{i-k-1}-\binom{i-l-1}{i-k-1})\),后面的组合数是分配编号的方案数,用了一个小容斥减去了不满足 \(x>v\) 的情况,可以做到 \(O(n^4)\)

这个东西显然无法继续优化了。你希望找到一个好的方式解决 \(x,v\) 的限制。考虑当树的形态确定而只需要计数可行标号数的时候,限制之间会形成一个 DAG,其中父亲向第一个儿子连边,儿子之间顺序连边,后一个儿子向前一个儿子的最后一个儿子连边。这是不好做的。但是对于某一个限制 \(x>v\),我们可以容斥掉它,用不存在这条性质的情况减去 \(x<v\) 的情况。对于前面的一种情况,显然是树;对于后一种情况,可以去掉儿子之间的顺序连边,也变成一棵树,树的拓扑序数量是好算的:\(\frac{n!}{\prod sz_i}\)

注意到第二种情况中,我们的限制树上会在 \(x\) 的下方接一个 \(v\) 作为儿子。在这样的情况下,我们重新设计 dp 状态:设 \(f_{i,j}\) 表示节点数量为 \(i\)、除了这 \(i\) 个节点外之后还要在限制树的根节点的最后一个儿子下面(也可以看做最后一个儿子之后)接一个大小为 \(j\) 的子树的决策系数,也即把 \(n!\) 提出来,在构建树的过程中计数树的形态及分母对答案的系数影响。注意由于当前的根节点有可能在父亲处被钦定合并上来一个新的子树,导致根节点在限制树上的子树大小变化,故我们先不计算整个树的大小在分母的贡献。仍然考虑枚举第一个子树去掉,下面进行转移的考察:

  • 若根节点只有一个子树,则有 \(f_{i,j}\gets \frac{1}{i+j-1}f_{i-1,0}\)
  • 否则枚举第一个子树的大小 \(k\),此时由于 \(j\) 的存在,合并带来的限制树子树大小影响已经被提前计算过,需要新乘进分母的只有第一个儿子在限制树上的子树大小(在它作为根的时候没有算),故有 \(f_{i,j}\gets\frac{1}{i+j-1}\sum_{k=2}^{i-2}(f_{k,0}-f_{k,i-1-k+j})\times f_{i-k,j}\)

最终答案为 \(\frac{1}{n}f_{n,0}\times n!\)。复杂度 \(O(n^3)\)

QOJ7677. Easy Diameter Problem

题意:给定 \(n\) 个点的树,每次删除任意一条直径的任意一个端点直到树删完为止,问可能的删除序列总数。\(n\leq 300\)

如果按照每一步操作去 dp,那么我们需要记录哪些被删除了、哪些没有,复杂度爆炸。于是我们考虑按照直径中点的移动进行 dp。

对于一个时刻,我们记录直径中点 \(u\)(可能在边的中点)和半径长度 \(r\) 两个信息。此时所有满足 \(dis_{x,u}=r\) 的点 \(x\) 都是某个直径的端点,任意两个不在同一方向上的端点都能组成一条当前的直径。在这个状态下,原树上所有满足 \(dis_{y,u}>r\) 的点 \(y\) 一定都被删除;所有满足 \(dis_{y,u}<r\) 的点一定都未被删除。

再考察一次移动 \((u,r)\to(v,r-\frac 12)\),其发生的充要条件是所有端点被删得只剩某一个方向保留,显然有 \(v\)\(u\) 向唯一有保留边界点的方向移动 \(\frac 12\) 距离到达的点。此时 \(u\) 的非 \(v\) 方向上的所有边界点都需要被删除;\(u\)\(v\) 方向上边界点可以被任意保留,但不能被删完。

一次移动对序列的影响主要由上述两个方面构成。非 \(v\) 方向的是一个全排列,容易处理;\(v\) 方向的点,由于它们来自 \(v\) 的不同方向,在下一步移动时根据方向不同会有不同的贡献,所以不能单纯记录还未填写的个数。但你发现对于 \(v\) 方向的所有点,它们可以开始填的时间是一致的,因此考虑先钦定所有点都不填,需要填的时候,再插入之前可以填的一个后缀中去。

注意到为了求出哪些点是任意保留的,我们需要记录这次移动的起始点。于是设 \(f_{i,u\to v,j}\) 表示当前直径长度为 \(i\)(这里指点长度),当前在 \(v\) 且是由 \(u\) 移动过来的,当前未填点的集合可以填入的后缀长度是 \(j\) 的方案数。注意到由于一次移动一定是由有效删除引发的,故未填点只能填后缀上 \(j\) 个元素的前面。根据 \(i\) 的奇偶性,我们可以知道 \(v\) 是在点上还是在边上(\(i\) 是奇数,则当前在点上),因此可以将 \(u\to v\) 用有向的树边编号代替,根据 \(i\) 判断是前半段还是后半段。下面考虑转移:

  • \(i\) 为奇数,也即此时在点上。枚举下一次移动的方向:
    • 移回去,此时所有需要删除的点即为上一次移动剩余的所有同向边界点,\(v\to u\) 方向上此次移动新增的同向边界点必须等 \(u\to v\) 移动完成后才能插入,也即不能插入在之前的后缀中。考虑枚举留下来的后缀 \(k\),设 \(c\) 表示 \(u\to v\) 移动的所有同向边界点,则 \(u\to v\) 移动前有 \(c-k\) 个这样的点被选过了,注意此时 \(k\geq 1\),有 \(f_{i-1,v\to u,k}\gets f_{i,u\to v,j}\times \binom ck\times k!\times (c-k)!\times \binom{c-k+j-1}{j-1}\),最后一个组合数是插入后缀(不能插入在序列最后)的方案数。
    • 继续前进,此时 \(v\to w\) 方向的边界点可以继续保留,且仍可以插在 \(j\) 中;非 \(u\)\(w\) 方向的边界点需要全部删除;\(u\) 方向上的边界点作为到达 \(v\) 后新增的部分,也需要全部删除,并且只能接在上一个后缀之后。设 \(u\) 方向上边界点个数为 \(c_1\),非 \(u\)\(w\) 方向上边界点个数为 \(c_2\),则有 \(f_{i-1,v\to w,j+c_1+c_2}\gets f_{i,u\to v,j}\times \binom{j+c_1+c_2}{c_2}\times (c_1)!\times (c_2)!\)
  • \(i\) 为偶数,也即此时在边上。枚举下一次移动的方向:
    • 移回去,此时转移方程与奇数情况下的完全一致。
    • 继续前进,此时唯一的区别是移动方向是确定的,也即 \(c_2\)\(0\),转移相同。

瓶颈在于移回去时,枚举 \(k\in[1,c]\)。注意到对于一个固定的中心,\(k\) 对所有直径求和的量级为 \(O(n)\),故转移均摊 \(O(1)\),总复杂度 \(O(n^3)\)

[ABC386G] Many MST

题意:对于所有 \(n\) 个点,边权在 \([1,m]\)\(m^{n(n-1)/2}\) 个无向完全图,求最小生成树边权和的和。

各种套路的叠加。

模拟最小生成树的过程,每次加入某一个权值的边。考虑利用差分拆贡献,将权值为 \(i\) 的边的贡献 \(i\) 拆成 \(1\sim i\) 每个位置各 \(1\),也即计算 \(d_i\) 表示权值大于等于 \(i\) 的边的个数,最小生成树边权则为 \(\sum_{i=1}^m d_i\)。假设加入了 \(\le i\) 的边后,还有 \(x\) 个连通块,则说明有 \(x-1\) 条边的权值 \(>i\),此处产生了 \(x-1\) 的贡献。

于是出现 \(O(m)\) 个问题,形如加入权值小于等于 \(i\) 的边后,每种完全图的连通块个数和是多少,则 \(d\) 用算出来的个数减去 \(m^{\frac{n(n-1)}{2}}\) 即可。

考虑如何求个数和?首先假设当前枚举到的边权为 \(x\)。对于连通块问题,不妨枚举编号最小的点所在的连通块大小进行 dp。设 \(f_i\) 表示 \(i\) 个点的完全图在此限制下的连通块个数和,\(g_i\) 表示 \(i\) 个点的连通完全图个数。对于 \(f\),枚举第一个点所在的连通块大小,并将其去掉:

\[f_n=m^{n(n-1)/2}+\sum_{i=1}^n\binom{n-1}{i-1}g_if_{n-i}(m-x)^{i(n-i)} \]

也即两个部分内部的方案,以及两个部分之间边的方案。注意到要求不连通,故两个部分之间的边权必须大于 \(x\)

对于 \(g\),可以容斥,用总方案数减去有多个连通块的方案数,于是仍然可以枚举一个连通块,剩下的部分任意连,有:

\[g_{n}=m^{n(n-1)/2}-\sum_{i=1}^{n-1}\binom{n-1}{i-1}g_i\times m^{(n-i)(n-i-1)/2}\times (m-x)^{i(n-i)} \]

递推预处理两个幂次即可做到 \(O(n^2)\) 求一个权值的答案。总复杂度做到 \(O(n^2m)\)

CF1707D Partial Virtual Trees

考虑给每一个点定一个 \(t_i\),表示它是在什么时候被删除的。一个合法的方案需要满足对于任意一个 \(i\),至多有 \(1\) 个儿子的子树内存在 \(t_x>t_i\),且 \(1\sim k\) 中的每一个都需要出现过。

不妨钦定有几个没有出现过,剩余的任意,容斥(二项式反演)即可去掉第二个限制。考虑设 \(f_{i,j}\) 表示 \(i\) 子树内的点在 \(j\) 时刻删完的方案数;对于 \(i=1\),我们另设 \(f\) 表示在 \(j\) 步内删完 \(2\sim n\) 所有点的方案。对于非 \(1\) 情况,有如下两种转移:

  • \(i\)\(j\) 时刻被删掉,则 \(f_{i,j}=\prod sumf_{v,j}\),其中 \(sumf\)\(f\) 的前缀和。
  • \(i\) 未在 \(j\) 时刻被删掉,则枚举最后一个被删掉的是儿子 \(p\) 的子树,有 \(f_{i,j}=f_{p,j}\times \sum_{t=1}^{j-1}\prod_{v\neq p}sumf_{v,t}\)。维护 \(sumf\) 的前后缀乘积,再把 prod 的部分边算边累加起来即可。

\(i=1\) 时只转移第一种即可。最后利用 \(f_1(j)\) 反演出答案。复杂度 \(O(n^2)\)

连续段 dp

P5999 [CEOI2016] kangaroo

题意:计数有多少个 \(n\) 的排列 \(p\),使得 \(p_1=s,p_n=t\) 且对于任意的 \(i\in[2,n-1]\),都有 \(i\) 相邻的值同时小于 \(i\) 或同时大于 \(i\)\(n\leq 2000\)

对于排列计数问题(或类似问题),这一类每个元素对相邻元素值有偏序要求的可以采用连续段 dp。我们按照值域顺序构建这个排列,维护不同的合法连续段,钦定同一个连续段之间不能再插入值、不同连续段之间至少插入一个值。这是连续段区间可以不重不漏计数的关键保障

对于此题而言,我们设 \(f_{i,j}\) 表示插入了 \(1\sim i\)\(i\) 个数,形成 \(j\) 个连续段的方案数。对于新插入的一个值,套路地考虑如下三种转移:

  • 该元素左右两侧还会插入另外的值。这显然满足条件,等价于新增加了一个段。
  • 该元素某侧会插入另外的值,这等价于接在了某个段的开头或结尾。它会导致一侧小一侧大,不合法。
  • 不再在两侧插入值,等价于合并两个段。同样满足条件。

这部分转移时要带位置系数。注意当 \(i>s\) 时,开头的一段已经被固定,不能在开头新开一段;\(i>t\) 时同理。对于 \(i=s,t\) 的情况,其位置已经被确定,它们都可以另起一段或直接接在现有段的开头结尾,特殊处理即可。

CF1515E.Phoenix and Computers

如果你按照电脑标号顺序插入,给每个时间分配电脑,那么最终限制是跨越的,不好做。不妨考虑给电脑分配时间。仍然设 \(f_{i,j}\) 表示有 \(i\) 个电脑分配好了时间,形成 \(j\) 个连续段的方案数。

  • 新增一个段,由于 \(i-1,i+1\) 时间都更晚,没有限制。
  • 延长某个段,可以开紧贴着的那个电脑,也可以开间隔一个的那个电脑,中间那个被自动打开,时间相同。
  • 合并两个段,不能只开一个来合并(若中间只有一个,那这个会在之前被自动打开),可以间隔两个(开左右的任意一个,另一个自动打开),也可以间隔三个(开最中间的一个,边上两个自动打开)。

时间复杂度 \(O(n^2)\)

P7967 [COCI2021-2022#2] Magneti

注意到一些性质:我们可以只考虑相邻两个磁铁中 \(r\) 较大的一个。正确性显然。

对于排列计数,朴素 dp 是困难的。在 \(n!\) 的引导下,我们尝试枚举每种排列计算答案。不妨算出每种排列所有磁铁的最小占用长度 \(s\),则剩余空格数为 \(p=l-s\)。我们需要在 \(s\) 个空格中可空地插入 \(n\) 个板子进行划分,故方案数为 \(\binom{p+n}{n}\)。于是我们只需要对每一个 \(s\) 计算有多少种排列的最小占用长度为 \(s\) 即可。

根据上面的结论,类似对相邻元素关系有要求的问题不妨使用连续段 dp。我们将 \(r\) 从小到大排序,逐个加入。考虑设 \(f_{i,j,k}\) 表示考虑前 \(i\) 个磁铁,目前连续段数量为 \(j\),共计占用了 \(k\) 个空格的方案数。

  • 新增一个段。这意味着和他相邻的磁铁 \(r\) 都不小于它,可暂时不考虑间隔的问题,有 \(f_{i,j,k}\gets f_{i-1,j-1k-1}\times j\)
  • 延长一个段。这意味着某一个单侧需要间隔 \(r_i-1\),另一侧暂时不考虑,有 \(f_{i,j,k}\gets f_{i-1,j,k-r_i}\times 2j\)
  • 合并两个段。这意味着两侧都要间隔 \(r_i-1\),有 \(f_{i,j,k}\gets_{i-1,j+1,k-2r_i+1}\times j\)

滚动数组即可,时间复杂度 \(O(n^2l)\)

反射容斥

基本模型形如给定两条直线 \(y=x+b\)\(y=x+c\),问从 \((0,0)\) 走到 \((n,m)\) 的、不碰到两条直线的方案数。我们将连续碰到某一条直线的事件缩起来,则每个路径的碰撞序列形如 BCBCBC...CBCBCB...。对于一次碰撞,我们可以将另一条直线和目标点同时关于碰撞直线作对称,然后考虑下一次碰撞,直到没有碰撞为止。每个碰撞序列会在其前缀和去掉开头的前缀处分别被算到 \(1\) 次(含空集),则令碰撞序列长度为 \(cnt\),贡献系数显然为 \((-1)^{cnt}\)。不妨分 B 开头和 C 开头分别计算,每次根据下面两个公式作对称即可。

  • \((n,m)\) 关于直线 \(y=x+b\) 的对称点为 \((m+b,n-b)\)
  • 直线 \(y=x+b\) 关于直线 \(y=x+l\) 的对称直线为 \(y=x+(2l-b)\)

实际上,通过计算每一次的对称点 \((x,y)\),可以推知一次先 \(B\)\(C\) 的对称会使得 \((n,m)\to(n+(b-c),m-(b-c))\),而一次变化后两直线的纵截距差 \((b-c)\) 不变;类似求得一次完整对称会使得两条直线的纵截距均增加 \(2(b-c)\),故可求出总对称的贡献为 \(\sum_{k\in N^*}\binom{n+m}{n+k(b-c)}-\binom{n+m}{n-(k-1)(b-c)-b}\)(另一侧只需要交换 \(b,c\) 进行计算)。故一次反射容斥复杂度为 \(O(\frac{n+m}{|b-c|})\)

由于反射容斥的规律性,每次翻折截距的变化和点的横坐标变化都是相当容易看出的(点的横坐标变化分奇偶)。事实上,计数条件可以写成一个很漂亮的,模 \(|b-c|\) 意义下的一个式子。

推导过程:

  • \((n,m,b,c)\to(m+b,n+b,b,2b-c)\to(n+(b-c),m-(b-c),3b-2c,2b-c)\),一组变换中所有值的变化量都只与 \(b-c\) 有关,故 \(b-c\) 持续不变。
  • \(k\) 次完整操作后变为 \((n+k(b-c),m-k(b-c),b+2k(b-c),c+2k(b-c))\)\(k-1\) 次完整操作再补一次 \(B\) 对称操作变为 \((m-(k-1)(b-c)+b+2(k-1)(b-c),n+(k-1)(b-c)-b-2(k-1)(b-c))\),化简得到 \((m+(k-1)(b-c)+b,n-(k-1)(b-c)-b)\)

例子:终点 \((n,n)\)\(y=x+1\)\(y=x-m\) 反射容斥,注意到直线每对称一次变化 \(m+1\),点的横坐标向前对称奇数次后变化 \(1\),偶数次变化 \(m\);向后是反过来的。因此所有 \((n-i)\bmod (m+1)=0\)\(i\),要加上 \(\binom{2n}{i}\);所有 \((n-i)\bmod (m+1)=m\)\(i\),要减去 \(\binom{2n}{i}\)

???

题意:有 \(n\) 个盒子,你需要在每个盒子里放入一个合法括号串,使得总左括号数目为 \(m\),且不存在一个盒子的左括号数目为 \(k\)。求总方案数。

我们先考虑没有限制的情况。设 \(f_{i,j}\) 表示考虑了 \(i\) 个盒子,放了 \(j\) 个左括号的方案数。则我们有如下转移:

\[f_{i,j}=\sum_{k=0}^jf_{i-1,j-k}\times C_k \]

其中 \(C\) 是卡特兰数。注意到卡特兰数有卷积形式的递推,考虑再把 \(f_{i-1}\) 展开一层。

\[\begin{aligned} f_{i,j}&=\sum_{x=0}^{j}\sum_{y=0}^{j-x}f_{i-2,j-x-y}\times C_x\times C_y\\ &=\sum_{t=0}^jf_{i-2,j-t}\sum_{x=0}^tC_xC_{t-x}\\ &=\sum_{t=0}^jf_{i-2,j-t}C_{t+1}\\ &=(\sum_{p=0}^{j+1}f_{i-2,j-p+1}C_p)-f_{i-2,j+1}\\ &=f_{i-1,j+1}-f_{i-2,j+1} \end{aligned} \]

于是我们得到了 \(f\) 的递推式,递推起点是 \(f_{0,i}=[i=0]\),也即存在唯一有值起点 \(f_{0,0}=1\)

然后考虑基于此加入不能为 \(k\) 的限制。我们有无限制的简单做法,于是考虑容斥,钦定某 \(x\) 个位置恰有 \(k\) 个左括号。有 \(ans=\sum_{x=0}^n(-1)^x\binom{n}{x}f_{n-x,m-xk}\times C_k^x\),可以 \(O(n)\) 计算,此时瓶颈在 \(O(n^2)\) 预处理 \(f\)

基于递推式 \(f_{i-1,j+1}=f_{i-2,j+1}+f_{i,j}\),考虑网格图优化,每一步可以看做往右一步或往左上一步。我们固定 \(i\) 轴不动,将 \(j\) 轴改为直线 \(y=-x\),整点位置不变,则此时有 \((i,j)\to (i+j,j)\)。此时唯一有值起点不变,终点做类似变换。注意当 \(i=0,j>0\) 时,\(f_{i,j}=0\),不满足上述走行规律,因此除起点外定义域为 \(\{(x,y)\mid x> y\}\),因此除 \((0,0)\) 以外不能碰到直线 \(y=x\),将 \((1,0)\) 看做起点单线反射容斥即可 \(O(1)\) 求解。也即 \(f_{x,y}\to (x+y,y)\),需要求的是从 \((1,0)\)\((x+y,y)\) 不碰到直线 \(y=x\) 的方案数,为 \(\binom{x+2y-1}{y}-\binom{x+2y-1}{y-1}\)。显然 \(y\)\(y-1\) 更靠近中轴。

总复杂度为 \(O(n)\),需要线性处理阶乘及做容斥,卡特兰数的 \(x\) 次幂可以递推计算。

posted @ 2025-03-15 23:37  烟山嘉鸿  阅读(225)  评论(0)    收藏  举报