dp 学习练习选讲
括号序列
- 对于括号排列这种题目,一个合法的方案就是维护一个
(为 \(1\),)为 \(-1\) 的一个前缀和数组,然后合法的充要条件就变为了这个前缀和数组的最小值为 \(0\) 且末尾为 \(0\)。 - 按外层配对括号 \(\texttt{(...)(...)...(...)}\) 拆开
- 拆出第一对配对括号,剩下视作整体 \(\texttt{(...)...}\)。
- 视作一个平面上的折线,进行容斥。
CF1781F
做法一:
对这个随时插入的序列用前缀和数组维护,我们发现我们不需要考虑末尾为 \(0\),只需要保证每个数都不小于 \(0\) 即可。
对于两种插入可能,假设在插入位置的前面的前缀和为 \(x\),则插入 () 就会有 \(x,x+1,x\),同理有 )( 是 \(x,x-1,x\)。
于是我们就可以把前缀和数组转化成一个可重集合,初始为 \(\{0\}\),每次操作就是等概率的在集合中抽出一个 \(x\),\(p\) 的概率在集合中放入 \(\{x+1,x\}\),\(1-p\) 的概率在集合中放入 \(\{x-1,x\}\),求最终所有元素非负的概率。
这时我们可以把概率转化为求出一个方案数:在进行 \(k\) 轮操作后等概率抽出一个 \(x\) 的概率是 \(\frac{1}{2k+1}\),而 \(p\) 也已知,每次相当于把 \(p\) 或 \(1-p\) 和 \(1\frac{1}{2k+1}\) 赋权给这个集合,我们要求的就变成了所有合法集合的权值积的和。
这个问题就可以考虑 dp。设 \(f(k,x)\) 表示初始集合数为 \(x\),在进行 \(k\) 次操作后所有合法集合的权值的和。则我们要求的就是 \(dp_{n,0}\)。
思考转移,对于一个状态 \(f(n,x)\),我们有 \(p\) 的概率和 \(1-p\) 的概率的两种转移:
即 \(\texttt{...(...)...}\) 三个位置继续放。
然后就成功有了 \(O(n^4)\) 的做法,但 \(n\le 500\)。
我们发现两种情况中重合了大部分的项,剩下的 \(p\times f(j,x+1)+(1-p)\times f(j,x-1)\),就可以把 \(i\) 消掉,转移就只关于 \(j\),剩下的预处理即可,时间复杂度 \(O(n^3)\)。
做法二:
我们发现我们可以根据方案 3,找到第一个匹配的括号,则剩下的就只有 2 个区域,于是我们就更快的得到了 \(O(n^3)\) 的转移方程:
吊打做法一
CF629C
Famil Door and Brackets.
我自己只能手切这种题了菜完了
本来是可以考虑有多少个排列包含 \(s\),但是我们发现总共要填的数不超过 \(2000\),而 \(|s|\) 又非常大,所以考虑对两边分别考虑,我们考虑 dp 求出长度为 \(i\),前缀数组大小为 \(j\) 的字符串数量,然后对前面长度和前缀大小进行考虑即可。
当然的还有一些类括号序列的结构。
CF888F
首先断环成链,那么对于一个区间 \([i,j]\),由于它是一个联通块,,那么区间有如下这两种形式:

其中 type 1 是 \((i,j)\) 没有连边的情况,type 2 是 \((i,j)\) 连了边的情况。但由于这是一棵树,所以这个 type 2 连通块必然有个断点,用枚举断点来转移。type1 按方式 3 转移。
具体的,有 \(dp_{i,j,0/1}\) 表示当前连通块为 \([i,j]\),\(0/1\) 表示 \((i,j)\) 间是否有连边。
那么转移就比较简单了:
- 对于 type1,\(dp_{i,j,0}=\sum_{k=i}^j dp_{i,k,1}\times (dp_{k,j,0}+dp_{k,j,1})\)
- 对于 type2,\(dp_{i,j,1}=\sum_{k=i}^{j-1} (dp_{i,k,0}+dp_{i,k,1})\times (dp_{k+1,j,1}+dp_{k+1,j,1})\)

浙公网安备 33010602011771号