2025.04.13 DP 专题
DDDDDDD
题单:https://vjudge.net/article/8396
ARC053D - 2 つの山札
题意:给定两个 \(n\) 阶排列 \(a_i\) 和 \(b_i\)。重复 \(2n-2\) 次操作:选择 \(a\) 与 \(b\) 之中长度不为 \(1\) 的一个,将选中序列第一个数字删除,未选中序列第一个数字加入 \(c\) 序列末尾(不删除)。求可能的 \(c\) 序列数量,对 \(10^{9}+7\) 取模。
\(1\le n\le 1000\)。
解法:用 DP 来解决这个问题。
设 \(p=a^{-1},q=b^{-1}\)。考虑如果知道 \(c_i\) 的值,这个 \(c_i\) 可能来自 \(a\) 中,也可能来自 \(b\) 中。
如果来自 \(a\) 中,那么 \(a\) 序列中 \(p_{c_i}-1\) 已经被删完了,也就是选中 \(a\) 序列恰好 \(p_{c_i}-1\) 次。由于填入的是第 \(i\) 个数,总共操作次数是 \(i\) 次,所以选中 \(b\) 序列的次数为 \(i-(p_{c_i}-1)\) 次。这样,我们就能确定 \(a\) 和 \(b\) 剩下的是什么。也就是说,操作 \(i\) 次后,\(a\) 和 \(b\) 序列剩下的形态只和 \(c_i\) 以及这个 \(c_i\) 来自哪个序列有关。
考虑将 \(c_i\) 与其来自哪个序列设进状态中。设 \(f_{i,j,0/1,0/1}\) 表示 \(c\) 序列前 \(i\) 位已经确定,而 \(c_{i}=j\),\(c_i\) 是否可能来自 \(a\),\(c_i\) 是否可能来自 \(b\)。
当前两维相同,而后两维不同时,需要对应 \(c\) 的前 \(i\) 位不同的方案,这样就保证不会算重。
根据后两维,可以确定 \(a\) 和 \(b\) 序列的形态,就可以知道 \(i+1\) 可能的情况只有 \(O(1)\) 种。稍微讨论一下就可以 \(O(1)\) 转移了。
我觉得一些计数题比较核心的想法还是要求同一个阶段的 DP 状态对应方案的前几个阶段的情况必定互不相同,来避免算重。
USACO24JAN - Merging Cells P
题意:有 \(n\) 个细胞,第 \(i\) 个大小为 \(a_i\)。每一次随机选择两个 相邻 细胞合并,合并后细胞的大小为两细胞大小之和,合并后编号为较大的细胞的编号(如果大小相同则取编号较大的)。求第 \(i\) 个细胞成为最终细胞的概率。
\(1\le n\le 5000\)。
解法:正难则反。考虑反过来,从最后的细胞 \([1,n]\) 拆分。可以认为这个过程是:将大区间拆成两个小区间,保留其中和最大的一个(如果和相同保留右边)。可以进行区间 DP。
设 \(f_{l,r}\) 表示最后答案由区间 \([l,r]\) 贡献的概率,边界为 \(f_{1,n}=1\)。转移时枚举断点 \(k\),拆分乘两个区间,可以做到 \(O(n^3)\)。如果填表转移加上前缀和优化可以做到 \(O(n^2)\)。
核心:正难则反。
EGOI 2022 - Lego Wall / 乐高墙
题意:要用乐高积木拼乐高墙。有 \(1\times 1\) 和 \(1\times 2\) 两种规格,不能旋转积木。要求拼出 \(n\times m\) 的墙,使得墙没有洞且连通。求方案数,对 \(10^{9}+7\) 取模。
\(1\le n\le 2.5\times 10^{5},1\le n\times m\le 5\times 10^{5}\)。
解法:用两种算法,平衡复杂度。
算法 1:容斥,设 \(f_i\) 表示 \(i\) 列积木墙的方案数(不要求连通),设 \(g_i\) 表示要求连通。则有 \(f_i\) 是第 \(i\) 个斐波那契数的 \(m\) 次方,和
即考虑之前已经形成了一个完整的 \(j\) 列连通块。复杂度 \(O(n^2)\)。
算法 2:设 \(f_{i,j}\) 表示前 \(i\) 列填完,第 \(i\) 列还有 \(j\) 行突出,则
则可以得到一个 \(O(nm^2)\) 的做法。
平衡两算法得到 \(O(nm^{\frac{4}{3}})\) 的算法。
核心:容斥,平衡复杂度。
Levenshtein Distance
题意:给定两个串 \(S\) 和 \(T\),对于每一个 \(0\le i\le k\),求 \(T\) 子串中,与 \(S\) 串编辑距离恰好为 \(i\) 的数量。
\(1\le \vert S\vert,\vert T\vert \le 10^{5},0\le k\le 30\)。
解法:不知道怎么想到的,对我来说非常困难的神秘 DP。
枚举 \(T\) 的一个后缀 \(T'\),求所有 \(T'\) 的前缀的贡献。
设 \(f_{i,j}\) 表示最大的 \(x\) 使得 \(S_{1...x}\) 与 \(T'_{1...x+j}\) 的编辑距离不超过 \(i\)。如果对于大的 \(x\),编辑距离不超过 \(i\),那么显然对于小的 \(x\),编辑距离也不会超过 \(i\)。
转移考虑:\(f_{i,j}\) 先匹配一段,加上 \(\operatorname{lcp}(s_{f_{i,j}+1...\vert S\vert},T'_{f_{i,j}+j+1...\vert T'\vert})\),这一步可以用 SA+KMP \(O(1)\) 求出。再进行转移:删除一个字符,转移到 \(f_{i+1,j+1}\);修改一个字符,加一之后转移到 \(f_{i+1,j}\);插入一个字符,加一之后转移到 \(f_{i+1,j-1}\)。
这个 DP 的状态数是 \(O(k^2)\) 级别的,转移是 \(O(1)\) 的。记 \(g_j\) 表示 \(T'_{1...\vert S\vert+j}\) 与 \(S\) 的编辑距离。求得 DP 数组后,对于 \(f_{i,j}=\vert S\vert\) 的 \((i,j)\),有 \(g_{j}=i\),全部取 \(\min\)。然而由于 \(f\) 数组记录的是最长的,所以有一些可能会被遗漏,所以再用 \(g_{j}=\min(g_{j},g_{j+1}+1)\) 来转移一下,最后统计答案。

浙公网安备 33010602011771号