浅谈插入DP
插入 DP
定义
插入 DP 是一类用于解决状态转移过程与相邻的已插入元素相关的 DP 问题,此类问题一般具有若只考虑在序列两端插入,问题将容易解决的特点。因此,插入 DP 是一类计数类 DP \(^{[1]}\)。
特征
-
题目特征
- 有排列性质
- \(100\le n \le 5\times 10^3\)
- 答案和排列的上升下降拐点有关
-
转移特征
插入操作仅在连续段的两端进行。
状态&转移
1. 状态的定义
一般情况 \(^{[2]}\) ,设 \(dp[i][j]\) 表示前 \(i\) 个元素,构成 \(j\) 个连续段的方案数。
2. 转移
(1) 考虑情况:
a. 插入元素成为新的一段
b. 插入元素至一个已有连续段的两端
c. 插入元素使两个已有连续段合并
(2) 转移方程
对于情况 a,有
其中,\((j+1)\) 表示可以在 \(j\) 段之间任意插入的位置。
对于情况 b,有
对于情况 c,有
其中,\(j\) 给连续段合并共有 \(j-1\) 中情况。
例题
1. [CF466D]Increase Sequence
题目大意
给定一个序列,可以对若干对区间 \([l,r]\) 中的数 \(+1\),且保证任意两个区间的左右端点不重合(即 \(l_1 \ne l_2\) 且 \(r_1 \ne r_2\))。
最终要求序列中所有元素值都等于 \(h\),请输出总方案数对 \(10^9+7\) 取模后的结果。
输入格式
第一行两个数字 \(n\) 和 \(h\)。
接下来一行 \(n\) 个数字 \(a_i\)。
输出格式
共一行,为总方案数对 \(10^9+7\) 取模后的结果。
说明/提示
\(1 \le n,h \le 2000\)
\(0 \le a_i \le 2000\)
分析
限制条件为要将所有元素变为 \(h\),求方案数。发现涉及连续段的求解操作且可以通过前缀和转化为段两端的操作,故考虑使用插入 DP。
:::info[如何构造?]
构造 \(dp[i][j][0/1]\) 表示插入前 \(i\) 个元素,有 \(j\) 个未闭合区间,是否同时在段两端 \(+1\)。
:::
:::info[如何转移?]
由以上构造分析,得出如下转移:
答案为 \(dp[n][0][0]+dp[n][0][1]\)。
:::
2. [Atcoder_dp_t]Permutation
题目描述
给定一个正整数 \(N\) 和一个由小于号 < 和大于号 > 组成的长度为 \(N-1\) 的字符串 \(s\)。
你需要找到一个排列 \((p_1,\ p_2,\ p_3,\ ...,\ p_N)\),满足对于任意 \(i\ (1 \leq i \leq N-1)\),如果 \(s_i\) 为 < 则 \(p_i < p_{i+1}\),如果 \(s_i\) 为 > 则 \(p_i > p_{i+1}\)。求满足性质的排列 \(p\) 的方案数对 \({10}^{9}+7\) 取模后的值。
输入格式
请按照以下格式输入:
\(N\)
\(s\)
输出格式
输出满足条件的方案个数对 \({10}^{9}+7\) 取模后的值。
数据范围与约定
- \(N\) 是正整数
- \(2 \leq N \leq 3000\)
- \(s\) 是一个长度为 \(N-1\) 的字符串
- 字符串 \(s\) 包含字符
<和>
注意输出结果要对 \({10}^{9}+7\) 取模。
显然,本题具有排列特征,故考虑插入 DP。
:::info[如何构造?]
设 \(dp[i][j]\) 表示第 \(i\) 个递增序列,上一个的可能长度为 \(j\) 的情况。
:::
:::info[如何转移?]
假设当前序列的长度为 \(x\),那么有
最终答案为 \(\sum_{j=0}^{n} \frac{dp[n][j]}{A_{n}^{j}}\times n!\)。
:::
注释&参考文献
[1] 计数类 DP,即计算满足特定限制的方案数的 DP。
[2] 问题所求的为满足某些限制的 \(n\) 的元素的排列数量。

浙公网安备 33010602011771号