Loading

动态规划做题记录

\(\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\) 的方案数,转移分两种情况:

\[f_{i,j}= \begin{cases} \sum_kf_{i-1,j},&\text{if }j=b_i\\ f_{i-1,j-b_i},&\text{otherwise} \end{cases} \]

可以发现只有当 \(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\) 的最小烦躁值,那么有

\[f_i=\min_{q_j\le p_i\land y_j=x_i}f_{j}+A(p_i-q_j)^2+B(p_i-q_j)+C \]

最后的答案为 \(\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\) 个位置不满足条件的方案数,那么有

\[ans=\sum_{i=0}^n(-1)^ih_i(n-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})\) 艘划艇的点数,那么有

\[f_{i,j}\leftarrow f_{pos,k}\times\binom{m+p_{j+1}-p_j-1}{m} \]

其中组合数是插板法。

在做一个前缀和优化即可。

\(\text{XV}\). [APIO2014] 序列分割

注意到最后分割后任意两个块的和都乘起来贡献到了答案,所以可以直接 DP。

\(f_{k,i}\) 表示前 \(i\) 个点割成 \(k\) 个块的最大答案,那么有转移

\[f_{k,i}=\max_{j<i}\{f_j+(s_i-s_j)s_j\} \]

对于每一层都做一遍斜率优化即可。

\(\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\) 三个数中的那一个,有转移

\[f_{n,x}=\sum_{i+j<n}\binom{n-1}{i}\binom{n-1-i}{j}\left(p\times f_{i,x}\times f_{j,x+1}\times f_{n-1-i-j,x}+(1-p)\times f_{i,x}\times f_{j,x-1}\times f_{n-1-i-j,x}\right) \]

适当变形后得到

\[f_{n,x}=\sum_j\binom{n-1}{j}\times(p\times f_{j,x+1}+(1-p)\times f_{j,x-1})\times\sum_i\binom{n-j-1}{i}f_{i,x}f_{n-1-i,x} \]

后面的式子可以预处理,这样就做到了 \(O(n^3)\)

\(\text{XVII}\). [ARC073F] Many Moves

水题。一个 naive 的想法是设 \(f_{i,j,k}\) 表示当前执行到第 \(i\) 个要求,两个棋子的位置分别为 \(j,k\) 的答案,转移平凡。

注意到 \(j,k\) 中有一个是 \(a_{i-1}\),且两者的相对顺序无关,所以可以去掉一维。

易得转移为

\[\begin{aligned} f_{i,j}&=f_{i-1,j}+\left|a_{i-1}-a_i\right|\\ f_{i,a_{i-1}}&=\min_jf_{i-1,j}+\left|j-a_i\right| \end{aligned} \]

将绝对值拆开后用线段树维护即可。

\(\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}\),所以有

\[f_{l,r,i}=f_{l,r,i+1}+f_{l,i-1,pos_{l,r,i}}\times f_{i+1,r,i+1} \]

\(\text{XXI}\). *[ARC121E] Directed Tree

这题可能想到容斥就做完了吧,但是奴才做不到啊!

考虑容斥,记 \(g_i\) 表示钦定 \(i\) 个不满足条件的方案数,那么有

\[ans=\sum_{i=0}^n(-1)^ig_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|\) 个点未被填放,所以方案数为

\[A_{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\) 个数的方案数,那么有

\[f_i=(V-c+1)\times f_{i-1}-(V-c)^k\times f_{i-k-1} \]

这里为什么是 \(i-k-1\),是因为这部分转移是要出去 \([i-k+1,i]\) 这段都大于 \(c\) 的贡献,此时要满足前面的条件,一定有 \(a_{i-k}=c\),所以不能从算上。

再考虑推广,现在重点在于 \(c_i\) 不同的段之间可能会相互影响。

假设有 \(c_{i-1}>c_i\),那么有

\[\begin{aligned} \min_{p=i-1}^{i+k-2}a_p&=c_{i-1}\\ \min_{p=i}^{i+k-1}a_p&=c_i\\ \end{aligned} \]

可以推出有

\[\begin{aligned} \forall i\le p\le i+k-2,a_p&\ge c_{i-1}>c_i\\ a_{i+k-1}&=c_i \end{aligned} \]

所以 \([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\) 种方案。因此

\[f_i= \begin{cases} f_{i-1}\times i,&a_i=0\\ f_{i-1}\times (i-1),&a_i=1 \end{cases} \]

统计答案就是平凡的了,设 \(ans_i\) 表示长度为 \(i\) 的排列的总贡献。前 \(i-1\) 个点的贡献会有方案数乘上 \(i\),可得贡献为 \(ans_i\times i\),而第 \(i\) 个点的贡献即为 \([a_i=0]\times f_{i-1}\),原因是显然的。

所以有

\[ans_i=ans_{i-1}\times 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\) 的期望操作次数,那么有

\[f_i=\frac{i}{n}+\frac{n-i}{n}(1+f_{i+1}+f_i) \]

解方程得到

\[f_i=\frac{n}{i}+\frac{n-i}{i}f_{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\) 的区间个数为

\[\sum\binom{cnt_i}{2} \]

然后考虑 DP。把前缀和画在图上就是一些类似于山峰的形状,考虑从上往下 DP。因为这样会有一个优美的性质,每次加数只会加在两头和缝隙之间。

于是就可以设计 DP \(f_{d,i,j,k}\) 表示考虑到第 \(d\) 层,一共用了 \(i\) 个点,和为 \(0\) 的区间个数有 \(j\) 个,第 \(d\) 层有 \(k\) 个缝隙的方案数,那么转移就枚举下一层有 \(l\) 个点,那么系数为

\[\binom{x-1}{k+1} \]

证明考虑插板法,把 \(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_{h,w}=f_{h+1,w}\times p^w+\sum_{i=1}^wf_{h+w,i-1}\times p^{i-1}\times(1-p)\times f_{h,w-i} \]

那么答案即为 \(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))\)

posted @ 2025-02-07 22:18  LIUIR  阅读(51)  评论(0)    收藏  举报