AtCoder DP Contest 笔记

蛮好的 DP 题组,很适合普及组入门 \(\to\) Link

A

\(f_i\) 代表走到 \(i\) 的答案。

\[f_i = \max(f_{i - 1} + \vert h_i - h_{i - 1}\vert, f_{i - 2} + \vert h_i - h_{i - 2}\vert) \]

B

\(f_i\) 代表走到 \(i\) 的答案。

\[f_i = \max_{j < i}(f_{j} + \vert h_i - h_j\vert) \]

和 A 是一样的。

C

\(f_{i, 0/1/2}\) 到了第 \(i\) 天选的什么的答案。

\[f_{i, 0} = \max(f_{i - 1, 1}, f_{i - 1, 2}) + a_i \]

\[f_{i, 1} = \max(f_{i - 1, 0}, f_{i - 1, 2}) + b_i \]

\[f_{i, 2} = \max(f_{i - 1, 1}, f_{i - 1, 0}) + c_i \]

D

01 背包。

E

注意到价值不太大,我们交换重量和价值。

对于每个价值,我们求出能够达到其的最小重量,于是就做完了。

F

\(f_{i, j}\) 为以 \(i,j\) 结尾的 lcs。

\[f_{i, j} = \max\left (f_{i - 1, j}, f_{i, j - 1}, [s_i = t_j]\times\left (f_{i - 1,j - 1} + 1\right )\right ) \]

然后记录以下 \(\mathrm{pre}\) 代表上次加一的 \(i\)。或者倒着做一遍也可以。

G

注意到图是拓扑序,所以按照拓扑序转移 \(f_x = \max(0,f_x, f_y) + 1\) 即可。

H

\[f_{i, j} = \begin{cases} f_{i - 1, j} + f_{i, j - 1} & \mathrm{if}\ a_{i, j} = \#,\\ 0 & \mathrm{otherwise}. \end{cases} \]

I

\(f_{i, j}\) 代表前 \(i\) 个硬币,正面朝上的有 \(j\) 个。

\[f_{i, j} = f_{i - 1, j - 1} \times (1 - p_i) + f_{i - 1, j} \times p_i \]

J

\(f_{i, j, k}\) 为当前有 \(1\) 个寿司的盘子个数 \(i\) 个,当前盘子中有 \(2\) 个寿司的盘子有 \(j\) 个,当前盘子中有 \(3\) 个寿司的盘子有 \(k\) 个。吃完需要的期望步数。

\[f_{i, j, k} = \frac{n}{i + j + k} +\frac{i}{i + j + k} \times f_{i - 1, j, k} + \frac{j}{i + j + k} \times f_{i + 1, j - 1, k} + \frac{k}{i + j + k} \times f_{i, j + 1, k - 1} \]

\(\dfrac{n}{i + j + k}\)\(n\) 个盘子中选到非零盘子的期望次数。

K

\(f_{i}\) 代表 \(i\) 个石头谁赢。

然后直接与起来转移即可,\(f_i \leftarrow f_{i - a_j}\)

L

区间 DP,就直接模拟博弈的过程。

但是有个很牛的 \(\mathcal{O}(n)\) 的贪心,把 \(a_i \le a_{i + 1}\land a_{i + 1}\ge a_{i + 2}\) 的三个数合并成 \(a_{i + 1} - a_i - a_{i + 2}\)

M

\(f_{i, j}\) 为前 \(i\) 个人分了 \(j\) 个糖的方案数,那么有转移:

\[f_{i, j} = \sum_{k = j - a_i} ^ j f_{i - 1, k} \]

\(f_i\) 作一遍前缀和秒了。

N

石子合并。

O

\(f_{i, S}\) 表示左边前 \(i\) 个点和右边 \(S\) 点集匹配的方案数。

\[f_{i, S} = \sum_{a_{i, k} = 1, k\in S} f_{i - 1, S \setminus k} \]

做完了。

P

树上独立集的方案数。

\(f_{u, 0/1}\) 代表 \(u\) 强制白色或黑色子树内的答案。

\[f_{u, 0} = 1 + \prod_{v\in S_u} (f_{v, 0} + f_{v, 1}) \]

\[f_{u, 1} = 1 + \prod_{v\in S_u} f_{v, 0} \]

Q

二维偏序模板题。

\(f_i\) 代表以 \(i\) 结尾的答案。

\[f_i = a_i + \max_{j < i\ \land\ h_j < h_i}f_j \]

树状数组维护即可。

R

矩阵加速 Floyed。我们考虑暴力转移。

\(f_{k, i, j}\)\(i\)\(j\) 之间走过 \(k\) 条边的路径数。

\[f_{k, i, j} = \sum_{l} f_{k - 1, i, l} \times f_{1, l, j} \]

然后这个东西和矩阵乘法长得一模一样。

快速幂就好了。

S

数位 DP。

\(f_{i, j, 0/1}\) 代表当前从低到高 \(i\) 位,当前所有数字和模 \(D\) 等于 \(j\),已经处理的位是否都等于 \(k\) 对应位。

\[f_{i, j, 0} = \sum_{m = 0}^{m\le 9} f_{i - 1, (j + m) \bmod D , 0} \]

\[f_{i, j, 1} =f_{i - 1, (j + k_i) \bmod D , 1} + \sum_{m = 0}^{m < k_i} f_{i - 1, (j + m) \bmod D , 0} \]

T

\(f_{i, j}\) 为前 \(i\) 个数填了 \(1\sim i\),第 \(i\) 位填 \(j\) 的方案数。

但是这样子不太对,我们发现没法转移。我们重新考虑 \(f_{i, j}\) 的意义,其实可以把 \(j\) 看作类似排名之类的东西。

具体一点,每次转移的时候,我们想象 \(1\sim i - 1\) 中所有大于等于 \(j\) 的数全部加一,这样就可以保证转移的正确性。

那么我们现在就有:

\[f_{i, j} = \begin{cases} \sum_{k = 1}^{j - 1} f_{i - 1, k} & \text{if}\ s_{i - 1} = \tt{<}, \\ \sum_{k = j}^{i - 1} f_{i - 1, k} & \text{if}\ s_{i - 1} = \tt{>}. \end{cases} \]

注意 \(i\) 是排名上界,转移时要注意。

U

\(f_{S}\) 为已选集合为 \(S\) 的答案,初始状态 \(f_S = \sum_{i < j} a_{i, j}\) 即什么都不分。

\[f_{S} = \max_{T\sub S}(f_T + f_{S\setminus T}) \]

时间复杂度 \(\mathcal{O}(2^n n ^ 2 + 3^n)\)

V

换根 DP,还不会,会了再写。

W

不会。

X

不会。

Y

经典容斥题目。

Z

不会。

posted @ 2025-07-28 16:16  Drifty  阅读(19)  评论(0)    收藏  举报