序列上的DP
trick
-
很多 01 串问题,都是固定 0 或者 1,移动另外一种,这样会方便考虑很多。
-
如果题目需要考虑当前位选还是不选时,你可以多记一位,也可以强制选,在向后转移的时候在考虑不选时的状态。
题目
P17337 【MX-X30-T3】宇宙分解 \(\checkmark\)
题目大意
给定 01 串,可任意次执行:若相邻为 01,可删除右边的 1,或将 01 交换为 10。求最终能得到多少种不同的 01 串,对 998244353 取模。
\(T \le 10^3\),所有测试 \(n\) 之和 \(\le 10^5\),所有串中 \(1\) 的个数总和 \(S \le 2\times 10^3\)。
解题思路
解题思路
启示这道题的数据范围提示的很明显,复杂度是要 \(O(nS)\) 的。
固定 0,操作就相当于选择左移 1 或者删掉这个 1,由于当前第 \(i\) 位的取值依赖于 \(i-1\) 位的情况,所以考虑 DP。
定义 \(f_{i,j}\) 表示强制选第 \(i\) 个 1,它的左边有 \(j\) 个 0,那么转移就是:
- 选 \(i-1\),\(dp_{i,j}=\sum_{k=0}^j dp_{i-1,k}\)
- 不选 \(i-1\),此时 \(i-1\) 在哪已经不重要了,贡献的序列都是相同的,所以直接加一即可。
这个很容易用前缀和优化,在加个滚动数组即可。
一个小提示,如果该序列前缀都是 1 的话,他们对答案没有任何贡献,不考虑。
启示: 很多这种 01 串问题,都是固定 0 或者 1,枚举移动另外一种,这样会方便考虑很多。还有一点,如果题目需要考虑当前位选还是不选时,你可以多记一位,也可以强制选,在向后转移的时候在考虑不选时的状态。

浙公网安备 33010602011771号