动态规划做题记录
\(\text{I}\). UVA1025 A Spy in the Metro
设 \(f_{i,j}\) 表示到达第 \(i\) 个车站,时间为 \(j\) 的最小等待时间,则有以下三种转移
- 原地不动,即 \(f_{i,j-1}+1\)。
- 从上一个车站坐车过来,即 \(f_{i-1,j-t_{i-1}}\)。
- 从下一个车站坐车过来,即 \(f_{i+1,j-t_i}\)。
最后答案即为 \(f_{n,T}\)。
\(\text{II}\). UVA116 Unidirectional TSP
考虑逆推。
设 \(f_{i,j}\) 表示从点 \((i,j)\) 到达最后一列的最小整数和,则可以从 \(f_{i-1,j+1},f_{i,j+1},f_{i+1,j+1}\) 转移过来。最后输出方案即可。
注意:这题只能逆推,因为要求前面的行号越小越好,而不是后面的行号。
\(\text{III}\). UVA11400 Lighting System Design
先将灯泡按电压从小到大排序,然后有一个结论:每一次选择的一定是一个区间。证明先估了。
于是可以设 \(f_i\) 表示前 \(i\) 个灯泡的最小费用,枚举一个 \(f_j\) 转移过来即可。
\(\text{IV}\). P6190 [NOI Online #1 入门组] 魔法
独立切紫祭
容易发现一定是把 \(k\) 次使用魔法的机会全部用完最优,在加上 \(k\) 远大于 \(n\),\(nk\) 又过不去,于是考虑矩乘。
考虑建出一张新图表示从 \(u\) 到 \(v\) 使用恰好一次魔法后的距离,那么从 \(1\) 到 \(n\) 走 \(k\) 步的最小距离即为答案。
但新图的边权任然不好求,于是考虑钦定一定是 \(u\) 到 \(v\) 路径上最后一条边使用魔法,这样的计算是平凡的。
注意最后可以在走一段不用魔法的距离。
时间复杂度为 \(O(n^3\log k)\)(不知道为什么出题人 \(n\) 只开到 \(100\))
\(\text{V}\). *[ARC108E] Random IS
直接按时间轴 DP 会有后效性,于是考虑从局部到整体。
考虑对于一个 \(l,r(l<r)\) 都被标记,那么区间 \([l,r]\) 内其他数选择的概率就与外面的数无关了。因为从外面选数限制没有那么严,所以只会影响内部选数的时间,这是无关紧要的。
然后就可以区间 DP 了。设 \(f_{l,r}\) 表示选定 \(l,r\) 后区间内其他数被选择的期望个数(注意不包括 \(l,r\)),那么转移可以枚举下一个选择的数 \(k(l<k<r\land a_l<a_k<a_r)\),从 \(f_{l,k}+f{k,r}\) 转移。每种情况有 \(\frac{1}{cnt_{l,r}}\) 的概率发生,且会让期望个数加一。(\(cnt_{l,r}\) 会每种条件的 \(k\) 的个数)
直接做是 \(O(n^3)\) 的,考虑优化。
首先 \(cnt_{l,r}\) 的计算是平凡的,关键在于 \(\sum_kf_{l,k}+f_{k,r}\) 的计算。考虑转化为 \(\sum_kf_{l,k}+\sum_kf_{k,r}\),其中每部分都是左端点或右端点固定下对值域在一定范围的求和,可以用树状数组优化。
于是可以做到 \(O(n^2\log n)\)。
\(\text{VI}\). *[ARC101E] Ribbons on Tree
首先有一个显然的 DP,设 \(f_{u,i}\) 表示 \(u\) 子树内有 \(i\) 个点向子树外匹配的方案数,此时若要覆盖 \(v\to u\),说明 \(i\ge1\)。转移可以枚举 \(v\) 子树中有多少个点向 \(u\) 的其他子树转移,即 \(f_{u,i}\times f_{v,j}\times\binom{i}{k}\times\binom{j}{k}\times k!\to f_{u,i+j}\)。
由于转移过于复杂,很难优化,于是正难则反,考虑容斥。
容易计算出钦定一个大小为 \(t\) 连通块内合法的方案数为 \(g(t)=g(t-2)\times(t-1)\),因为没有顺序,所以考虑编号最小的点的配对方案。
重新设 \(f_{u,i}\) 表示点 \(u\) 所在的连通块大小为 \(i\) 的方案数。那么转移分两种:
-
合并 \(u,v\) 所在的连通块,\(f_{u,i}\times f_{v,j}\to f_{u,i+j}\)。
-
断开 \(u,v\) 这一条边,\(f_{u,i}\times f_{v,j}\times g(j)\to f_{u,i}\)。
最后的答案即为 \(\sum_i f_{1,i}\times g(i)\)。
\(\text{VII}\). P5369 [PKUSC2018] 最大前缀和
观察一个前缀 \(a_{[1,i]}\) 成为最大前缀的充要条件:
-
\(\forall_{1<j\le i}sum_{j\to i}\ge0\),否则就可以删掉这一段使答案更小。
-
\(\forall_{j>i}sum_{i+1\to j}<0\),否则就可以加上这一段使答案更大。
于是就可以 DP 了。设 \(f_{S}\) 表示选 \(S\) 为前缀答案的方案数,\(g_{S}\) 为选 \(\overline{S}\) 为前缀答案的方案数。\(f\) 的转移可以从后往前加数,\(g\) 的转移可以从前往后加数,然后是平凡的。
但 \(sum_{1\to i}\) 不一定 \(\ge0\),所以可以枚举第一个数来计算答案。
\(\text{VII}\). *[ARC106E] Medals
可以发现答案的下界为 \(k\times n\),因为每个人至少要有 \(k\) 个奖牌;上界为 \(2\times n\times k\),因为可以依次给每个人发奖牌,每个人最多花 \(2\times k\) 天。
于是就可以先二分一个答案 \(m\),然后发现可以建图跑二分图完美匹配。具体来讲,对于每个人建 \(k\) 个点表示获得的奖牌,再与这 \(m\) 天匹配。
根据 Hall 定理,一个二分图,左部点集合为 \(L\),右部点集合为 \(R\),要存在完美匹配的充要条件为:对于每个 \(S\in L\),存在 \(T\in R\),满足 \(T\) 中所有点均与 \(S\) 有连边且 \(\left|T\right|\ge\left|S\right|\)。
假设左部点为每个人,右部点为每天。那么当 \(S\) 限制最严格是一定是把某个人的 \(k\) 个点全部选上,因为它们连向的点是相同的,于是只有 \(2^n\) 种不同的 \(S\)。
考虑枚举 \(S\) 来判断,那么有 \(T=\{x|x\le m,\exists_{i\in S}(i,x)\in E\}\)。
正难则反,考虑判断 \(\overline{T}\) 是否合法,即判断 \(\left|T\right|\le day-\left|S\right|\)。因为有 \(\overline{T}=\{x|x\le m,\forall_{i\in S}(i,x)\not\in E\}\),即 \(\forall_{(i,x)\in E}i\not\in S\to\forall_{(i,x)\in E}i\in\overline{S}\)。
于是可以用高维前缀和算出连边集合为 \(S\) 的子集的天数,然后就可以 \(O(1)\) 判断每个 \(S\) 是否合法了。
时间复杂度 \(O(n^2k+2^n2\log nk)\)。题解中有人用模拟网络流做到了 \(O(n^3k)\)。
\(\text{VIII}\). CF1485F Copy or Prefix Sum
考虑最朴素的 DP,设 \(f_{i,j}\) 表示考虑前 \(i\) 个位置,和为 \(j\) 的方案数,转移分两种情况:
可以发现只有当 \(j\) 等于 \(b_{[1,i]}\) 的一段后缀和时才有值,于是将时空复杂度均降到 \(O(n^2)\)。
记 \(g_{i,j}=f_{i,sum_i-sum_j}\),其中 \(sum\) 为 \(b\) 的前缀和。那么每次只会令 \(g_{i,i-1}=\sum_kg_{i-1,k}\),和让某些 \(g_{i,k}\) 为零。这样的 \(k\) 要满足 \(sum_i-sum_k=sum_i\Longleftrightarrow sum_k=sum_{i-1}\)。
可以发现原本 \(g_{i-1,k}\) 有值的 \(k\) 只有一个,因为其他的已经被变成 \(0\) 了,于是可以直接修改并维护出 \(\sum_jg_{i,j}\)。
时间复杂度 \(O(n)\)。
\(\text{IX}\). *P5468 [NOI2019] 回家路线
由于会有往回走的路,所以对于站台 DP 不太可行。于是考虑对每一辆列车 DP。
设 \(f_i\) 表示坐第 \(i\) 辆列车到达 \(y_i\) 的最小烦躁值,那么有
最后的答案为 \(\min_{y_i=n}f_i+q_i\)。
观察到有平方的形式,于是考虑斜率优化。但 \(q_j\le p_i\land y_j=x_i\) 的限制不太好做。
考虑把一辆列车拆成两部分,一部分是在 \((y_i,q_i)\) 的位置插入,另一部分是在 \((x_i,p_i)\) 的位置查询。这样每次查询就变成查询第一维相同且第二维更小的点。
考虑把所有点按第二维排序,对于每一个第一维都开一个单调队列来做息率优化。这样就可以优化到 \(O(n\log n)\) 了,瓶颈在排序。
\(\text{X}\). [ABC328G] Cut and Reorder
可以发现只会进行一次操作一,且可以放在第一次执行。此时操作二的代价为 \(\sum\left|a_{p_i}-b_i\right|\)。
观察到 \(n\le22\),于是考虑状压。设 \(f_{i,S}\) 表示前 \(i\) 个位置的状态为 \(S\) 的最小代价。转移可以枚举一个连续段 \([l,r]\) 放在 \([i+1,i+r-l+1]\) 的位置上,代价为 \(c+\sum_{j=1}^{r-l+1}\left|a_{l+j-1}-b_{i+j-1}\right|\)。
发现 \(i=\operatorname{popcnt}(S)\),于是可以省掉一维,状态数优化到 \(O(2^n)\)。
在分析时间复杂度,对于一个长为 \(k\) 的连续段,会在 \(2^{n-k}\) 个状态中被枚举,且共有 \(n-k+1\) 个这种连续段,所以总时间复杂度为 \(\sum_{k=1}^nO((n-k+1)2^{n-k})=O(n2^n)\)。
\(\text{XI}\). *[ABC134F] Permutation Oddness
好题啊!
考虑把每个位置 \(i\) 看成左部点,每个值 \(p_i\) 看成右部点,这样就变成了二分图匹配问题。
对于这种贡献,可以考虑将绝对值拆开,即分讨 \(i\) 与 \(p_i\) 的大小关系。
那么这样就可以设 \(f_{i,j,k}\) 表示考虑前 \(i\) 个左部点和右部点的匹配,其中有 \(j\) 个左部点是向后匹配的(同时也有 \(j\) 个右部点向后匹配),且怪异度为 \(k\) 的方案数,那么转移可以分讨:
-
若左部点 \(i\) 匹配右部点 \(i\),那么有 \(f_{i-1,j,k}\to f_{i,j,k}\)。
-
若两个点都向后匹配,那么有 \(f_{i-1,j-1,k+2i}\to f_{i,j,k}\)。
-
若两个点都向前匹配,那么有 \(f_{i-1,j+1,k-2i}\times(j+1)^2\to f_{i,j,k}\)。
-
若两个点一个向前,一个向后,那么有 \(f_{i-1,j,k}\times2j\to f_{i,j,k}\)。其中乘 \(2\) 是因为可以选择是哪个点向前匹配。
直接转移即可。
\(\text{XII}\). [ABC200F] Minflip Summation
首先可以猜到对于确定的 \(s\),答案为其 \(0\) 段个数和 \(1\) 段个数的 \(\min\)。
但有个 \(\min\) 不好计数,于是考虑再次转换。由于 \(0\) 段和 \(1\) 段个数最多差 \(1\),所以若记 \(l=\sum_{i=1}^{n-1}[s_i\not=s_{i+1}]\),那么答案为 \(\lceil\frac{l}{2}\rceil\)。
由于有取模不能向上取整,所以要记录 \(l\) 的奇偶性。于是设 \(f_{i,0/1,0/1}\) 表示考虑到位置 \(i\),\(l\) 的奇偶性,\(s_i\) 的值。类似地设 \(g_{i,0/1,0/1}\),转移是平凡的。
再注意到 \(k\) 很大且有重复转移,于是考虑矩乘。然后就做完了
时间复杂度 \(O(8^3(n+\log k))\)。
\(\text{XIII}\). *[ABC214G] Three Permutations
感觉挺典的,虽然我不会。
注意到限制强于错排,直接考虑容斥。记 \(h_i\) 表示有 \(i\) 个位置不满足条件的方案数,那么有
然后在看到排列 \(p,q\),于是想到从 \(p_i\) 向 \(q_i\) 连边。这样相当于让边去匹配点,若匹配到两端则不合法。
于是考虑对每个置换环分别 dp。设 \(f_{i,j,0/1}\) 表示考虑环上前 \(i\) 个点,钦定了 \(j\) 个位置非法,且最后一条边是否钦定匹配它的出点。(因为不钦定和匹配入点都对后续 dp 无影响,所以一起考虑)那么转移分讨是否钦定 \(i\):
-
若不钦定 \(i\),
\[f_{i,j,0}=f_{i-1,j,0}+f_{i,j,1} \] -
若钦定 \(i\),
\[f_{i,j,0}=f_{i-1,j-1,0}\\ f_{i,j,1}=f_{i-1,j-1,0}+f_{i-1,j-1,1} \]
因为构成了一个环,所以可以钦定第一条边的状态跑两边 dp。注意特判长为 \(1\) 的环。
最后在用背包把每个环的答案拼起来即可。
\(\text{XIV}\). *[APIO2016] 划艇
暴力 DP 是设 \(f_{i,j}\) 表示学校 \(i\) 派出 \(j\) 艘划艇的方案数,转移是平凡的。
发现 \(l_i\le r_i\le10^9\),这启发离散化。
考虑设 \(f_{i,j}\) 表示学校 \(i\) 派出的划艇数在 \([p_j,p_{j+1})\) 时的方案数。为方便要把 \(r+1\) 离散化。
转移枚举上一个满足派出划艇数不在 \([p_j,p_{j+1})\) 的学校 \(p\),以及它派出的划艇区间 \([p_k,p_{k+1})\)。同时记 \(m\) 为 \(p+1\to i\) 中能派出 \([p_j,p_{j+1})\) 艘划艇的点数,那么有
其中组合数是插板法。
在做一个前缀和优化即可。
\(\text{XV}\). [APIO2014] 序列分割
注意到最后分割后任意两个块的和都乘起来贡献到了答案,所以可以直接 DP。
设 \(f_{k,i}\) 表示前 \(i\) 个点割成 \(k\) 个块的最大答案,那么有转移
对于每一层都做一遍斜率优化即可。
\(\text{XVI}\). CF1781F Bracket Insertion
易得总方案数为 \((2n-1)!!\),所以只需计数。
考虑把 (
看作 \(1\),)
看作 \(-1\)。那么合法等价于任意位置值非负。(因为总和一定为 \(0\))
考虑在值为 \(x\) 的位置后面插入。若插入 ()
,则会加入 \(x+1,x\);若插入 )(
,则会加入 \(x-1,x\)。
于是现在有一个初始为 \(\{0\}\) 的可重集。每次从中取出一个 \(x\),并将 \(x-1,x\) 或 \(x+1,x\) 加入集合中。问操作方案数。
顺着时间线加入要关心 \(x\) 是否为 \(0\),不好计数。于是考虑逆着做。
设 \(f_{n,x}\) 表示初始时为 \(\{x\}\),操作 \(n\) 次后的方案数,枚举剩下的 \(n-1\) 次操作时对 \(x,x+1,x\) 三个数中的那一个,有转移
适当变形后得到
后面的式子可以预处理,这样就做到了 \(O(n^3)\)。
\(\text{XVII}\). [ARC073F] Many Moves
水题。一个 naive 的想法是设 \(f_{i,j,k}\) 表示当前执行到第 \(i\) 个要求,两个棋子的位置分别为 \(j,k\) 的答案,转移平凡。
注意到 \(j,k\) 中有一个是 \(a_{i-1}\),且两者的相对顺序无关,所以可以去掉一维。
易得转移为
将绝对值拆开后用线段树维护即可。
\(\text{XVIII}\). *CF888F Connecting Vertices
非常吉利的题号!
先断环成链,那么要求每条边所覆盖的区间要么不交,要么包含。
这启示区间 DP。设 \(f_{l,r}\) 表示区间 \([l,r]\) 连在一起的方案数:
-
若在 \(l\) 和 \(r\) 之间连边,则枚举断点 \(k\),将 \([l,k]\) 连在一起,\([k+1,r]\) 连在一起,这部分贡献为 \(\sum f_{l,k}\times f_{k+1,r}\)。
-
不在 \(l\) 和 \(r\) 之间连边,则枚举连接 \(l\) 和 \(r\) 的点 \(k\),在 \([l,k]\) 之间连边,\([k,r]\) 之间连边,这部分贡献为 \(\sum f_{l,k}\times f_{k,r}\)。
直接这样算是错的,因为第二种情况会记重。
考虑给状态加一维 \(0/1\) 表示是否在 \(l\) 和 \(r\) 之间连边,在限制第二种情况枚举的 \(k\) 满足 \(l\) 和 \(k\) 之间连边就不会记重了。
\(\text{XIX}\). *[JOISC2020] 治療計画
直接按时间轴 DP 不好做,于是考虑对序列 DP。
一个治疗计划 \((t,l,r)\),对应平面上一条线段 \(((l,t),(r,t))\),以此斜边做等腰直角三角形,就是这个计划能覆盖的范围。而两次治疗的衔接恰好对应一条斜率为 \(1/-1\) 的线段。
所以对于方案 \(i,j\),若 \(r_i-l_j\ge\left|t_i-t_j\right|\),就从 \(i\) 向 \(j\) 连一条边权为 \(c_j\) 的。那么最短路即为答案。
注意到 \(j\) 的每条入边的边权是相同的,所以 Dijkstra 时只会被加入堆中一次。直接用线段树维护即可。
时间复杂度 \(O(n\log n)\)。
\(\text{XX}\). *[AGC056B] Range Argmax
观察到一个序列 \(x\) 可能由多个排列 \(p\) 生成,不好计数。于是考虑一种能让序列 \(x\) 唯一对应一个 \(p\) 的映射:
-
每次考虑 \(p\) 中的最大值的位置,记为 \(i\)。那么可以将跨过 \(i\) 的区间全部删掉,因为它们的 \(x\) 时已知的。
-
为了唯一对应,每次找到可能成为最大值的位置中最靠左的那一个,再考虑这样会有什么限制。
-
右边显然是一个子问题,故而只需考虑左边。
-
因为不能再靠左,所以对于左边的最大值的位置 \(j\),至少要有一个区间同时覆盖的 \(i\) 和 \(j\),否则交换 \(p_i\) 和 \(p_j\) 任然可以对应同样的序列 \(x\)。
-
换句话说,若记 \(pos_{l,r,i}=\min_{i\in[l_o,r_o]\subseteq[l,r]}l_o\),要满足 \(j\ge pos_{l,r,i}\)。
这样分割区间的方式可以想到区间 DP。设 \(f_{l,r,i}\) 表示区间 \([l,r]\) 最大值位置 \(\ge i\) 的方案数,转移只需考虑最大值位置为 \(i\) 的方案数,其余的继承 \(f_{l,r,i+1}\),所以有
\(\text{XXI}\). *[ARC121E] Directed Tree
这题可能想到容斥就做完了吧,但是奴才做不到啊!
考虑容斥,记 \(g_i\) 表示钦定 \(i\) 个不满足条件的方案数,那么有
然后就可以树形 DP 了。设 \(f_{u,i}\) 表示 \(u\) 的子树内钦定 \(i\) 个点不满足条件的方案数,那么转移就是树形背包合并子树,然后在考虑选择点 \(u\) 带来的贡献。
最后有 \(g_i=(n-i)!f_{1,i}\),表示未被钦定的点可以任选。
\(\text{XXII}\). [PKUWC2018] 随机算法
考虑状压 DP,设 \(f_{s,i}\) 表示考虑了点集 \(s\) 内的点,独立集为 \(i\) 的方案数。这里的考虑表示所有在独立集中的点临点的并集。
那么转移可以枚举一个 \(j\not\in s\) 加入独立集,再计算一下转移系数:这些点都要在 \(j\) 后面,共有 \(n-\left|s\right|-1\) 个位置,且还有 \(\left|\complement_{Nv(j)}Nv(j)\cap s\right|\) 个点未被填放,所以方案数为
\(\text{XXIII}\). UVA12099 The Bookcase
直接 DP 不仅要记录 \(\sum w_i\),还要记录 \(\max h_i\),时间复杂度爆炸。
注意到转移顺序无关,所以考虑按 \(h_i\) 从大到小加入,每次加入时只需判断书架是否为空。而这可以判断 \(\sum w_i\) 是否为 \(0\)。
于是只需记录 \(\sum w_i\) 即可,时间复杂度 \(O(n\left(\sum w_i\right)^2)\)。
\(\text{XXIV}\). *UVA1628 Pizza Delivery
一眼区间 DP,但贡献不好提前计算,于是考虑再增加一维状态。
注意到只需知道后续操作中送出外卖的次数就可以提前计算贡献,所以把这也加入状态中。
由于送完一个区间后要么在左端点,要么在右端点,所以只需记录 \(0/1\)。
转移就枚举下次直接送客户 \(i\),并跳过中间的客户。
但为了计算答案方便,状态的定义要为已送完区间 \([l,r]\) 的客户,再送其他客户的最小花费。否则无法计算答案。
\(\text{XXV}\). [USACO19JAN] Train Tracking 2 P
先考虑所有 \(c_i\) 都相同怎么做。
此时只有两种情况,要么 \(=c\),要么 \(>c\)。类似于 ABC279G,设 \(f_i\) 表示 \(i\) 个数的方案数,那么有
这里为什么是 \(i-k-1\),是因为这部分转移是要出去 \([i-k+1,i]\) 这段都大于 \(c\) 的贡献,此时要满足前面的条件,一定有 \(a_{i-k}=c\),所以不能从算上。
再考虑推广,现在重点在于 \(c_i\) 不同的段之间可能会相互影响。
假设有 \(c_{i-1}>c_i\),那么有
可以推出有
所以 \([i,i+k-1]\) 这段区间内的数都不用再考虑了,因为之前已经考虑过了。这等价于删掉前 \(k\) 个数。
类似地,若 \(c_i<c_{i+1}\),则要删掉后 \(k\) 个数。
然后就转换为了独立的情况,直接乘法原理即可。
\(\text{XXVI}\). *CF1806D DSU Master
这都不会做,必须加训。
易得每个时刻一个联通块内的点的编号构成一段区间。
考虑什么时候 \(1\) 的儿子个数会发生改变。
假设此时 \(p_i=x\),那么要满足以下三个条件:
-
\(1\) 到 \(x\) 已经联通。
-
\(a_x=0\)。
-
\(1\) 还没有父亲。
这样就会使得 \(x+1\) 所在连通块的根变成 \(1\) 的儿子。
于是考虑设计状态 \(f_i\) 表示长度为 \(i\) 的排列,操作完使得 \(1\) 到 \(i+1\) 联通且 \(1\) 为根节点的排列个数。转移分讨 \(a_i\) 的取值:
- 若 \(a_i=0\),此时无论放到哪里都不会使得 \(1\) 不为根,有 \(i\) 种方案;否则当且仅当放在最后一个位置不合法,有 \(i-1\) 种方案。因此
统计答案就是平凡的了,设 \(ans_i\) 表示长度为 \(i\) 的排列的总贡献。前 \(i-1\) 个点的贡献会有方案数乘上 \(i\),可得贡献为 \(ans_i\times i\),而第 \(i\) 个点的贡献即为 \([a_i=0]\times f_{i-1}\),原因是显然的。
所以有
\(\text{XXVII}\). [AGC009C] Division into Two
感觉这题放到现在大概就是 2000~2200 的水平。
一个暴力的 DP 是设 \(f_{i,j}\) 表示两个集合最后一个位置分别为 \(i,j\) 的方案数。但这样状态数就是 \(O(n^2)\) 的,不太好优化。
考虑换一种 \(O(n^2)\) 的 DP。设 \(f_{i,0/1,0/1}\) 表示将点 \(i-1\) 划到集合 \(X/Y\),点 \(i\) 划到集合 \(X/Y\) 的方案数,转移就枚举上一个和 \(i\) 再同一个集合内的位置 \(j\),从 \(f_{j+1,0/1,0/1}\) 转移过来。注意特判一些边界情况。
然后发现转移的 \(j\) 在一段区间内,直接用双指针维护区间端点+前缀和即可。
\(\text{XXVIII}\). [六省联考 2017] 分手是祝愿
先考虑如何求出一个序列的最小操作次数。一个显然的贪心是从大到小,要操作就操作。
接着注意到一个状态真正有用的只有其最小操作次数 \(t\),操作对了 \(t\) 就减一,操作错了 \(t\) 就加一。而操作对的概率为 \(\frac{t}{n}\)。
于是就可以设计 DP \(f_i\) 表示从 \(i\) 转移到 \(i-1\) 的期望操作次数,那么有
解方程得到
如果初始状态的 \(t\le k\),那么答案就是 \(t\)。
否则答案就是 \(k+\sum_{i=k+1}^tf_i\)。
\(\text{XXIV}\). [PA 2019] Muzyka pop
因为 \(\operatorname{popcount}\) 的存在,不好直接下手,于是考虑数位 DP。
考虑按二进制从高位到低位断开,那么每次显然是断成一些区间。
于是可以设 \(f_{bit,l,r,0/1}\) 表示考虑了低 \(bit\) 位,区间 \([l,r]\) 内的数除了低 \(bit\) 位都相同,低 \(bit\) 位是否满足 \(\le\) \(m\) 的低 \(bit\) 位的方案数。转移就枚举端点+分类讨论一下。
时间复杂度 \(O(n^3\log m)\)。
\(\text{XXX}\). [AGC043D] Merge Tripletss
考虑找到一个序列能被生成的充要,然后再据此 DP。
有一个显然的结论是对于任意的 \(i\),不存在 \(a_i>\max(a_{i+1},a_{i+2},a_{i+3})\)。证明就是一个块内就只有 \(3\) 个元素。
换句话说,这个结论即为取出前缀 \(\max\) 后据此划分整个序列,每一段的长度 \(\le3\)。
但这只是必要条件,并不充分。一个反例就是 4 3 5 2 6 1
。
注意到 4 3 5 2 6 1
不合法是因为无法用 \(3\) 个长为 \(2\) 的段拼出长为 \(1\) 的段。于是可以再得出一个必要条件:长为 \(2\) 的段的个数 \(\le\) 长为 \(1\) 的段的个数。
这两个条件加起来就充分了,具体考虑构造性证明:
-
一个长为 \(3\) 的段就直接分在一个块内。
-
对于一个长为 \(1\) 的段,找到一个长为 \(2\) 的段并将这两个拼起来。
-
剩下的都是长为 \(1\) 的段,三个三个的拼起来即可。
然后 DP 就设 \(f_{i,j}\) 表示考虑前 \(i\) 个数,长为 \(1\) 的段的个数 \(-\) 长为 \(2\) 的段的个数为 \(j\) 的方案数。转移就枚举下一个段的长度,并乘上对应的系数即可。
\(\text{XXXI}\). [ARC117E] Zero-Sum Ranges 2
先考虑如何对一个已知的序列快速求出答案。若记 \(cnt_i\) 表示前缀和为 \(i\) 个位置个数(包括 \(0\)),那么和为 \(0\) 的区间个数为
然后考虑 DP。把前缀和画在图上就是一些类似于山峰的形状,考虑从上往下 DP。因为这样会有一个优美的性质,每次加数只会加在两头和缝隙之间。
于是就可以设计 DP \(f_{d,i,j,k}\) 表示考虑到第 \(d\) 层,一共用了 \(i\) 个点,和为 \(0\) 的区间个数有 \(j\) 个,第 \(d\) 层有 \(k\) 个缝隙的方案数,那么转移就枚举下一层有 \(l\) 个点,那么系数为
证明考虑插板法,把 \(x\) 个求放到 \(k+2\) 个盒子里,不能为空。
但这样是 \(O(n^6)\) 的,可能不能通过。注意到 \(d\) 没什么用,直接不枚举即可。
但这样无法考虑前缀和小于 \(0\) 的位置,这是就需要把两部分拼起来。
此时 \(f_{i,j,k}\) 对应的就是 \(f_{2*n+1-i,m-j,k-1}\),原因画一画图就知道了。
\(\text{XXXII}\). *[HAOI2016] 字符合并
可以发现类似于石子合并的过程,且 \(n\le300,k\le8\),于是考虑区间 DP + 状压。
考虑设 \(f_{l,r,s}\) 表示区间 \([l,r]\) 合并后状态为 \(s\) 的最大价值。因为能合并就肯定合并,所以有 \(\left|s\right|<k\)。
一个 native 的转移就是枚举端点 \(i\) 后再枚举左右两边的状态,然后再枚举把 \([p,p+k-1]\) 这一段合并成一个数。但这样应该是 \(O(kn^32^{2k})\) 的,完全不能通过。
应该可以把合并的过程放到后面去做,然后变成 \(O(n^32^{2k})\),但没什么用。
注意到很多转移其实是没用的。考虑每次只加入长度为 \(1\) 的状态,然后再考虑合并。容易证明这可以覆盖所有情况。这样是 \(O(n^32^k)\) 的,还是不能通过。
又因为能合并就合并,所以一个长为 \(len\) 的区间合并后的长度为 \(len\bmod(k-1)\)。那么转移枚举的数量就除以了 \(k\),时间复杂度变为 \(O(\frac{n^3}{k}2^k)\),可以通过。
\(\text{XXXIII}\). *[NOI2017] 泳池
先容斥成 \(\le k\) 的概率。
考虑 DP,设 \(f_{h,w}\) 表示考虑有 \(w\) 列的情况,此时保证下方的 \(h\) 行全部安全时所以子海域枚举均满足 \(\le k\) 时的概率。(注意概率不考虑下方的 \(h\) 行)
转移就枚举第 \(h+1\) 行第一个不安全的位置,有
那么答案即为 \(f_{0,n}\)。
因为满足面积 \(\le k\) 的矩形只有 \(O(n+k\log k)\) 个,所以暴力做是 \(O((n+k)^2\log k)\)。
考虑把 \(f_{0,w}\) 单独拿出来转移。若 \(w>k\),那么前面的 \(f_{h+1,w}\times p^w\) 值为 \(0\),可以忽略。而后面的就类似于一个常系数齐次线性递推的形式。
于是直接做就行了,因为数据范围较小,所以可以暴力乘和取模。
\(\text{XXXIV}\). *P11958 「ZHQOI R1」划分
又被薄纱了。
观察到答案 \(>0\) 当且仅当要么全为正,要么全为负,此时只会分一段,直接特判。
剩下的情况一定满足每一段的 \(\min\times\max<0\),否则可以和别的段合并。
考虑一个段,只选择其中的 \([L,R]\) 这一段产生 \(a_L\times a_R\) 的贡献,其他部分无贡献。若这一段同时包含了 \(\min\) 和 \(\max\),那么贡献不变;否则贡献一定会减小。
于是就可以转换题目:选择一些不交的区间 \([l_i,r_i]\),最小化 \(\sum a_{l_i}\times a_{r_i}\)。
这可以直接 DP,设 \(f_i\) 表示前 \(i\) 个数的答案,分类讨论 \(i\) 不被区间覆盖和作为一个区间右端点的情况。
\(\text{XXXV}\). P11957 「ZHQOI R1」幂和
考虑先将 \((i+x)^k\) 拆开,转为对于每个 \(j\in[1,k]\) 求出 \(\sum_{i=0}^n(-1)^{\text{popcnt}(i)}i^j\)。
因为 \((-1)^{\text{popcnt}(i)}\) 不好量化,于是考虑直接暴力数位 DP,转移的过程同样拆开幂次。这样是 \(O(k^2\log n)\) 的。
然后可以用 NTT 优化到 \(O(k\log k\log n)\)。
\(\text{XXXVI}\). JOI2024 Final 马拉松比赛 2
容易观察到一个结论:终点 \(T\) 两侧的球,一定是先拿距离远的。
于是任意时刻被拿的球的区间为一段前缀+一段后缀。考虑设 \(f_{l,r,0/1}\) 表示已经拿了区间 \([1,l)\cup(r,n]\) 的球,且现在停留在 \(l/r\) 上的最小时间。转移是平凡的。
询问的时候就查询从离 \(T\) 最近的两个位置走过来。为了区分起点是 \(1/n\),另设 \(g\) 表示相同的含义(只有起点不同)。
然后就可以做到 \(O(n^2+q)\) 了。
注意到 \(T\le5\times10^5\),假设去重后还有 \(m\) 个位置,那么所需时间至少为 \(1+2+\cdots+m=O(m^2)\)。所以若 \(m>2\times10^3\),答案一定是 No
。
于是可以去重后做 DP,这样就是 \(O(m^2+q)\) 的。
\(\text{XXXVII}\). [USACO24OPEN] Activating Robots P
考虑以机器人为参照物,那么所有其他物体都会有一个顺时针 \(\frac{1}{k}\) 的速度。而此时人的速度为顺时针 \(\frac{k+1}{k}\) 或逆时针 \(\frac{k-1}{k}\),且放机器人还要等激活点到来。
然后可以设 \(f_{S,i}\) 表示放了集合 \(S\) 内的机器人,且当前在点 \(i\) 的最短时间。转移就枚举下一个放机器人的位置 \(j\),然后计算一下转移系数。可以用二分求出最近的激活点,时间复杂度为 \(O(2^RR^2\log N)\)。
考虑优化,发现每个 \(f\) 转移的最后都为进行一个映射 \(g\)。于是不妨改变 \(f\) 的状态为进行映射前,转移是就先映射在转移,这样就可以优化为 \(O(2^RR(\log N+R))\)。