HYODP

DP 模型刷题板

按组筛选,进度保存在本机。
0当前显示
0重点剩余
0复习中
0未完成

题目列表

1
CF1155D Beautiful Array
重点

题意:给定长度为 nn 的数组 a1,,ana_1,\dots,a_n 和一个整数 xx。你可以选择至多一个连续子段,将其中所有元素乘上 xx。求操作后的最大子段和(子段可为空,空段和为 00)。

数据n3×105n \leqslant 3\times 10^5ai109|a_i| \leqslant 10^9x109|x| \leqslant 10^9。时限 2s。

Hint 1

模型分析

至多一段乘 xx → 序列被切成「普通 → 乘 xx → 普通」三段(任一段可为空)。

Hint 2

DP 对象与生成方式

ii 结尾的最大子段和,但要额外记录当前处于第几阶段。dp[i][0/1/2]dp[i][0/1/2] 三状态递推。O(n)O(n)

启示

把"是否进入过某特殊状态"显式编码为状态的一维。

2
选做

题意:长度为 nn 的序列只含 1 和 2。允许翻转一个连续子段恰好一次。求操作后最长不降子序列的长度。

数据n2000n \leqslant 2000。时限 1s。

Hint

翻转一段 = 允许序列走 1→2→1→2 的四段式。等价于在 dp[i][1..4]dp[i][1..4] 上做状态机转移。

3
重点

题意:长度为 NN 的字符串,字符集 A~J(共计 10 种)。求有多少个子序列满足:同种字符在子序列中出现的位置必须连续(即不能出现 ABA 型穿插)。结果对 998244353998244353 取模。

数据N1000N \leqslant 1000。时限 2s。

Hint 1

模型转化

"不能出现 ABA" → 等价于:每种字符一旦开始选就必须连续选完,之后不能再回头选。

Hint 2

DP 对象与必要性推导

从左到右逐个字符决策选/不选。需要知道:上一个选的字符是谁(判断能否继续同种),以及历史上已经用过哪些字符(用过就不能再新开)。

dp[i][last][mask]dp[i][last][mask] = 前 ii 个字符,上一位选的字符为 lastlast(0~9),已选字符集合为 maskmask(二进制)。O(N10210)O(N \cdot 10 \cdot 2^{10})

4
重点

题意:长度为 nn 的正整数序列 a1,,ana_1,\dots,a_n。求最长的子序列,使得相邻两个元素不互质(即 gcd>1\gcd > 1)。

数据n105n \leqslant 10^5ai105a_i \leqslant 10^5。时限 2s。

Hint 1

模型分析

gcd>1\gcd > 1 等价于有共同质因子。转移时不能只看上一个元素是谁——如果 aia_iai1a_{i-1} 不互质但和 ai2a_{i-2} 互质,照样能接在 ai2a_{i-2} 后面。

Hint 2

DP 对象的重定义(核心!)

DP 对象不是"以第 ii 个元素结尾",而是以某个质因子 pp 结尾

dp[p]dp[p] = 最后一个数含有质因子 pp 的最长子序列长度。对每个 aia_i,枚举其所有质因子 pp,用 maxqaidp[q]+1\max_{q \mid a_i} dp[q] + 1 更新所有 dp[p]dp[p]O(na)O(n\sqrt{a})O(nloga)O(n\log a)(预处理质因子)。

启示

DP 对象不一定是你第一反应的那个。这是 Step 2 的精髓。

5
重点

题意:给定两个 1n1 \sim n 的排列 P1,P2P_1, P_2。求它们的最长公共子序列(LCS)长度。

数据n105n \leqslant 10^5。时限 1s,内存 125MB。

Hint 1

模型转化(关键!)

两个排列的 LCS 可以转化为 LIS。令 pos[x]pos[x] = xxP2P_2 中的位置。将 P1P_1 的每个元素替换为 pos[P1[i]]pos[P_1[i]],然后在新序列上求 LIS。O(nlogn)O(n\log n)

启示

Step 1 的模型简化——把"两个序列的匹配"变成"一个序列的单调性"。

6
CF597C Subsequences
普通

题意:给定一个 1n1 \sim n 的排列和整数 kk。求长度为 k+1k+1 的最长上升子序列(严格递增)的个数

数据n105n \leqslant 10^5k10k \leqslant 10。时限 1s。

Hint

dp[len][pos]dp[len][pos] = 以 pospos 结尾、长度为 lenlen 的 LIS 个数。BIT(树状数组)每层维护前缀和优化转移。O(nklogn)O(nk\log n)

7
P1020 导弹拦截
选做

题意:一套导弹拦截系统,第一发可拦截任意高度的导弹,之后每一发不能高于前一发。给定导弹高度序列,求:(1)一套系统最多拦截多少枚;(2)拦截所有导弹最少需要几套系统。

数据:导弹数量 105\leqslant 10^5,高度 5×104\leqslant 5\times 10^4。时限 1s。

Hint

(1)最长不升子序列(LDS),O(nlogn)O(n\log n)。 (2)Dilworth 定理:偏序集的最小链覆盖 = 最长反链长度 → 求 LIS 长度即可。

8
重点

题意:长度为 nn 的字符串 sstt。每次操作可将 ss 的任意一个字符往左移动任意步(越过前面的字符)。求最少操作次数使 s=ts = t。若无法做到输出 1-1

数据n2000\sum n \leqslant 2000(多组数据)。时限 2s。

Hint 1

模型分析

往左移动 = 字符可以"延后匹配",即允许跳过前面的字符。若 sstt 的多重集不同则无解。

Hint 2

DP 对象

dp[i][j]dp[i][j] = ss 的前 ii 个字符中,有多少个已经被匹配到了 tt 的前 jj 个。当 si=tjs_i = t_j 时可向前匹配;否则要么跳过 sis_i(往左移),要么 tjt_j 等待后方字符。O(n2)O(n^2)

9
P2758 编辑距离
选做

题意:字符串 AA 通过三种操作变成 BB:插入一个字符、删除一个字符、替换一个字符。每步代价均为 1。求最小总代价。

数据A,B2000|A|, |B| \leqslant 2000。时限 1s。

Hint

经典双序列 DP。设 Di,jD_{i,j} 表示 A[1..i]A[1..i]B[1..j]B[1..j] 的编辑距离。若 Ai=BjA_i = B_jDi,j=Di1,j1D_{i,j}=D_{i-1,j-1};否则 Di,j=1+min(Di1,j,Di,j1,Di1,j1)D_{i,j}=1+\min(D_{i-1,j},D_{i,j-1},D_{i-1,j-1})

10
普通

题意:字符串 AA(长 nn)、BB(长 mm)。对于任意 1in1 \leqslant i \leqslant n1jm1 \leqslant j \leqslant m,令 Li,jL_{i,j} 表示 A[1..i]A[1..i]B[1..j]B[1..j] 的 LCS 长度,定义 f(i,j)=4Li,jijf(i,j)=4L_{i,j}-i-j。求 maxi,jf(i,j)\max_{i,j} f(i,j)

数据n,m5000n, m \leqslant 5000。时限 1s,内存 256MB。

Hint

dp[i][j]=dp[i][j] =Ai,BjA_i, B_j 结尾4Li,jij4L_{i,j}-i-j 的最大值。

转移:若 Ai=BjA_i = B_jdp[i][j]=max(dp[i1][j1]+2,  0)dp[i][j] = \max(dp[i-1][j-1] + 2,\; 0);否则 dp[i][j]=max(dp[i1][j],dp[i][j1])1dp[i][j] = \max(dp[i-1][j], dp[i][j-1]) - 1。答案取 dpdp 表中最大值。

11
ABC212E Safety Journey
普通

题意nn 个点的完全图,删去其中 mm 条边。从点 1 出发,每次走到相邻点,走恰好 kk 步回到任意点。求方案数,对 998244353998244353 取模。

数据n,m,k5000n, m, k \leqslant 5000。时限 2s。

Hint

正难则反。设 TsT_s 为第 ss 步到达所有点的总方案数,Rs,vR_{s,v} 为沿被删边走到 vv 的非法方案数,则 Ds,v=Ts1Ds1,vRs,vD_{s,v}=T_{s-1}-D_{s-1,v}-R_{s,v}Rs,vR_{s,v} 可枚举被删边求和。O((n+m)k)O((n+m)k)

12
P3195 玩具装箱
重点

题意nn 个玩具依次排列,第 ii 个长度 cic_i。将玩具切分成若干连续段,每段用一个容器装。一个装了 [l,r][l, r] 的容器代价为 (rl+i=lrciL)2(r - l + \sum_{i=l}^r c_i - L)^2。求最小总代价。

原题数据n5×104n \leqslant 5\times 10^4L107L \leqslant 10^7ci107c_i \leqslant 10^7。时限 1s。

若尚未学习斜率优化,本题数据为 n5000n \leqslant 5000

Hint 1

模型分析

玩具是有序的 → 按顺序分段即可。不需要考虑排列或子集。

Hint 2

DP 对象

DiD_i = 前 ii 个玩具的最小代价。转移枚举上一段的结尾 jjDi=minj(Dj+Cj,i)D_i=\min_j(D_j+C_{j,i}),其中 Cj,i=(SiSj+ij1L)2C_{j,i}=(S_i-S_j+i-j-1-L)^2。做到这里即可,复杂度 O(n2)O(n^2)

Hint 3

原题优化

单调队列维护下凸壳,斜率优化。O(n)O(n)

13
CF229D Towers
重点

题意nn 座塔楼排成一列,高度 hih_i。每次操作可将相邻两座合并(新高度 = 两高度之和)。求最少合并次数,使得最终序列非递减(每个塔楼高度 \leqslant 下一个)。

数据n5000n \leqslant 5000hi105h_i \leqslant 10^5。时限 2s。

Hint 1

模型分析

最终每个塔楼是原序列中连续一段。塔楼数量越多,合并次数越少(答案 =nk= n - kkk 是最终塔楼数)。目标:最大化 kk

Hint 2

换维(核心!)

直接记"上一段的和"作为状态量级太大。改用上一个区间的起始位置间接表示。

dp[i][j]dp[i][j] = 末尾为 ii、当前段起点为 jj 时,最多能有几段。转移:枚举下一个段的结尾 kk,要求 sum[j..i]sum[i+1..k]sum[j..i] \leqslant sum[i+1..k]O(n2)O(n^2)

14
CF1312E Array Shrinking
重点

题意:给定数组 aa。若存在相邻且相等的两个数 ai=ai+1a_i = a_{i+1},可将其替换为一个 ai+1a_i+1。求最终数组的最短可能长度

数据n500n \leqslant 500ai1000a_i \leqslant 1000。时限 2s。

Hint 1

初始直觉

只记 dp[l][r]dp[l][r] = 区间 [l,r][l,r] 能合并成的最短长度。但问题来了:什么时候两段可以进一步合并成一段?

Hint 2

状态扩充至封闭

两段能合并     \iff 各自都能合并到只剩一个数,且这两个数相等。所以必须额外记录能合并到只剩一个数时,那个数是多少。

增设 b[l][r]b[l][r] = 区间 [l,r][l,r] 若能合并成单独一个数时的值(否则为 0)。当 dp[l][k]=dp[k+1][r]=1dp[l][k] = dp[k+1][r] = 1b[l][k]=b[k+1][r]b[l][k] = b[k+1][r] 时,dp[l][r]=1dp[l][r] = 1b[l][r]=b[l][k]+1b[l][r] = b[l][k] + 1O(n3)O(n^3)

启示

状态不够就扩充,直到关于转移封闭——反复走 Step 2→3。

15
重点

题意:长度为 nn 的 01 串。每次操作:选择一段连续相同字符消除,得分为该段长度的对应分值 alena_{len}a1,,ana_1,\dots,a_n 给定)。消除后两侧字符串拼接。求最大总分。

数据n100n \leqslant 100ai109a_i \leqslant 10^9。时限 2s。

Hint 1

模型分析

这题不是普通的区间 DP——因为消完左边后,右边可能和更左边的东西连在一起。单靠区间两端的信息不够。

Hint 2

“挂载”状态(核心!)

dp[l][r][k]dp[l][r][k] = 区间 [l,r][l,r],且左边还有 kk 个和 ala_l 相同的字符等着一起消(这些字符来自更左侧,被之前的消除操作"遗留"下来)。最大得分。

转移:(1)先把这额外 kk 个和 ala_l 一起消掉;(2)在区间内找另一个和 ala_l 相同的位置 mm,把中间消掉,然后把 ala_l 的"负载"传递给 mmO(n4)O(n^4)

启示

区间 DP 有时需要让"区间外的信息"穿透边界写入状态。

16
重点

题意nn 个非负整数 aia_i。选择一个非负整数 xx,使得 maxi(aix)\max_i (a_i \oplus x) 最小。求这个最小值。

数据n105n \leqslant 10^5ai<230a_i < 2^{30}。时限 1s。

Hint 1

DP 对象

DP 的对象不是按下标分割,而是一个"在某一位上的数字集合"。

Hint 2

生成方式:按位切分

从最高位(第 29 位)向下递归。设当前位为 bb。若所有 aia_i 在第 bb 位上全是 0(或全是 1),则可以选 xx 的同位让答案的这一位为 0;否则无论如何这一位答案必定为 1,然后按 0/1 分成两组递归取 min\minO(nlogmaxa)O(n\log \max a)

启示

分段不一定按下标——按最高位 0/1 切分也是合法的"段"

17
P1880 石子合并
选做

题意nn 堆石子围成一圈,第 ii 堆有 aia_i 颗。每次合并相邻两堆,代价 = 两堆石子数之和,合并后新堆石子数为两者之和。求最小和最大总代价。

数据n100n \leqslant 100(朴素),n300n \leqslant 300(可用四边形不等式优化)。时限 1s。

Hint

断环为链(将数组复制一份接在末尾)。Dl,r=mink(Dl,k+Dk+1,r)+Sl,rD_{l,r}=\min_k(D_{l,k}+D_{k+1,r})+S_{l,r}O(n3)O(n^3)

18
重点

题意nn 个正整数 aia_i。求有多少个排列 pp 满足以下条件:若 pi>maxj<ipjp_i > \max_{j < i} p_j(即 pip_i 刷新了前缀最大值),则必须满足 pi2×maxj<ipjp_i \geqslant 2 \times \max_{j < i} p_j。结果对 998244353998244353 取模。

数据n5000n \leqslant 5000ai109a_i \leqslant 10^9。时限 2s。

Hint 1

模型分析

只有刷新最大值的元素有限制。非刷新元素只需要老老实实出现在某个已确定的最大值后面即可,谁先谁后无所谓。

Hint 2

只 DP 关键元素

aa 升序排序。DiD_i = 以 aia_i 作为最后一个"刷新最大值"的元素的方案数。转移:Di=DjPremD_i=\sum D_j\cdot P_{\mathrm{rem}},求和范围是所有满足 2ajai2a_j\leqslant a_ijj,其中 PremP_{\mathrm{rem}} 表示用组合数处理中间的非关键元素。O(n2)O(n^2)

19
重点

题意:求 1n1 \sim n 的排列中有多少个满足 i=1npii=k\sum_{i=1}^n |p_i - i| = k。结果对 109+710^9+7 取模。

数据n50n \leqslant 50kn2k \leqslant n^2。时限 2s。

Hint 1

模型分析

pii\sum |p_i - i| = 直观上就是每个位置和它的值之间的"距离"。如果按值从小到大插入排列,会有一种优雅的计数方式。

Hint 2

开口贡献法

从小到大插入值 v=1,2,,nv = 1, 2, \dots, n。当前有 jj 个"开口"(已经知道这个位置将来要放某个值,但现在还没放)。

dp[v][j][s]dp[v][j][s] = 已放入值 1v1 \sim v,当前 jj 个开口,已累积距离和 ss 的方案数。插入 vv 时有三种操作:

  • 放自己位置:开口数不变
  • 关闭一个开口:jj 减 1,距离累计
  • 新开一个开口:jj 加 1

O(n2k)O(n^2 k)

启示

排列 DP 不需要知道每个值去了哪个具体位置——"开口数"这种全局汇总就够了

20
重点

题意:求 1n1 \sim n 的排列中,恰好kk 个位置满足 pii=1|p_i - i| = 1(即"好位置",值刚好在相邻位置)的排列数。对 109+710^9+7 取模。

数据n1000n \leqslant 1000knk \leqslant n。时限 2s。

Hint 1

容斥转化

"恰好 kk 个"不好直接数。改为先 DP 算出"至少 jj 个好位置"的方案数 f[j]f[j],再用二项式反演容斥回恰好:ans[k]=j=kn(1)jk(jk)f[j]ans[k] = \sum_{j=k}^n (-1)^{j-k} \binom{j}{k} f[j]

Hint 2

DP“至少”

dp[i][j][0/1][0/1]dp[i][j][0/1][0/1] = 考虑到位置 ii,已钦定 jj 个好位置,ii 是否已占用、i+1i+1 是否已占用的方案数。注意:好位置的定义是"值 ii 放在位置 i1i-1i+1i+1"。O(n2)O(n^2)

21
重点

题意nn 个位置排成一行,nn 个人按随机顺序依次入座。每人选一段连续的全空位置坐下,若有多段可选则等概率随机。求所有人坐下后占据的总座位数的期望(即期望最终被占据的座位数)。

数据n500n \leqslant 500。时限 2s。

Hint 1

模型分析

多个"极长连续被占用段"之间完全无关——因为没人会跨过空位去选另一段的座位。所以可以分别 DP 一个连续段,最后用组合数把各段合并。

Hint 2

最后一个人切分法(核心!)

考虑一个被占用的连续段 [l,r][l, r]。找最后一个进入该段的人,他坐在某个位置 mm。他把该段切成左右两个独立的子段,分别 DP。子段间无关 → 组合数合并。

dp[i][j]dp[i][j] = ii 个位置、ii 个人的段的总占用期望(含方案数),通过枚举最后一个人的位置来转移。O(n3)O(n^3),优化可至 O(n2)O(n^2)

启示

第二类方法的典范——找"最后决策点"→ 发现独立性 → 拆分处理。

22
CF1799G Count Voting
选做

题意nn 个人分成 tt 个团队(第 ii 人属团队 cic_i)。每人必须投一票给同团队的另一个人。第 ii 人恰好得 targetitarget_i 票。求合法投票方案数,对 998244353998244353 取模。

数据n200n \leqslant 200targeti=n\sum target_i = n。时限 2s。

Hint

逐团队处理。团内每个人投出的票的去向可以通过组合数算。把团内投票方案数作为物品,跨团队做背包合并。团队内部:将投票视为排列,最后除以阶乘去重。

23
CF1784D Wooden Spoon
选做

题意2n2^n 人参加单淘汰赛(标准锦标赛树)。求每个人获得"木汤匙"(即所有比赛全败——说明他第一轮就遇到最终的冠军)的方案数。输出 2n2^n 个答案。

数据n20n \leqslant 20。时限 2s。

Hint

按锦标赛层级自底向上处理。dp[mask]dp[mask] 从低层级向高层级合并败者集合。组合数处理层级间的选手分配。O(n2n)O(n2^n)

24
P4163 排列
选做

题意nn 个正整数,重新排列。求有多少种排列使相邻两数之和为完全平方数。对 109+710^9+7 取模。

数据n15n \leqslant 15ai109a_i \leqslant 10^9。时限 1s。

Hint

dp[mask][last]dp[mask][last] = 已选集合为 maskmask、最后一个选的是 lastlast 的方案数。检查相邻和是否为完全平方数即可转移。O(2nn2)O(2^n n^2)

25
CF1580D Subsequence
普通

题意:数组 a1,,ana_1,\dots,a_n。选一个子序列(设选了 mm 个,对应原下标 i1<i2<<imi_1 \lt i_2 \lt \dots \lt i_m,令 bj=aijb_j = a_{i_j})。价值定义为 V=S1S2V=S_1-S_2,其中 S1S_1 是所有 bjb_j 之和,S2S_2 是所有连续子段最小值之和。求最大价值。

数据n4000n \leqslant 4000ai109a_i \leqslant 10^9。时限 2s,内存 256MB。

Hint

在数组 aa 上建笛卡尔树(以最小值为根)。选子序列等价于在笛卡尔树上选一些节点,且每个节点贡献为(自身值 ×\times 被包含的次数)。DP 对象从排列变成了树。dp[u][j]dp[u][j] = uu 的子树中选了 jj 个点的最大价值。O(n2)O(n^2)

26
选做

题意nn 个职员构成一棵树(上下级关系)。每个职员有快乐值 rir_i(可正可负)。选一些人参加舞会,要求:若一个人被选,他的直接上司不能同时被选。求最大总快乐值。

数据n6000n \leqslant 6000128ri127-128 \leqslant r_i \leqslant 127。时限 1s。

Hint

dp[u][0/1]dp[u][0/1] = 不选/选 uu 时,uu 的子树的最大总快乐值。选 uu 时儿子都不能选;不选 uu 时儿子可选可不选(取 max\max)。O(n)O(n)

27
普通

题意nn 个节点的树,每个节点黑色(1)或白色(0)。可以切掉任意条边。求方案数使得每个连通块中恰好有一个黑色节点。对 109+710^9+7 取模。

数据n105n \leqslant 10^5。时限 1s。

Hint

dp[u][0]dp[u][0] = uu 所在连通块中黑点数为 0 的方案数;dp[u][1]dp[u][1] = 黑点数为 1 的方案数。合并儿子 vv 时:若切边,vv 必须自己有 1 个黑点;若不切边,vv 的黑点数必须为 0。O(n)O(n)

28
P2014 选课
选做

题意nn 门课,部分课有先修课(形成森林)。每门课有学分 sis_i。必须选恰好 mm 门课,且选了某门课必须先选它的先修课(以及先修的先修……)。求最大学分。

数据n,m300n, m \leqslant 300si20s_i \leqslant 20。时限 1s。

Hint

树上背包。加一个 0 号虚拟根把森林变成树。dp[u][j]dp[u][j] = uu 子树中选 jj 门课(必须选 uu)的最大学分。合并儿子:dp[u][j+k]=max(dp[u][j]+dp[v][k])dp[u][j+k] = \max(dp[u][j] + dp[v][k])O(nm2)O(nm^2)

29
CF1187E Tree Painting
重点

题意nn 个点的树,初始全白。第一步任选一点染黑;之后每一步选一个与已有黑点相邻的白点染黑。每次染黑的得分为:该白点当前所在白色连通块的大小。求最大总分。

数据n2×105n \leqslant 2\times 10^5。时限 2s。

Hint 1

调整法证明无关性(核心!)

关键发现:一旦选定第一步染黑的点(即根),后续操作顺序不影响总分!因为无论什么顺序,每个点染黑时的得分始终等于以根为起点时它的子树大小。

证明:交换相邻两次染色,只有当两个点在不同子树时才会互相影响——但交换前后总得分相同。

Hint 2

退化为选根问题

问题转化为:选根最大化子树大小之和。先 DFS 任选一个根算出初始得分,然后换根:dp[v]=dp[u]+n2×size[v]dp[v] = dp[u] + n - 2\times size[v]O(n)O(n)

启示

Step 1 决定了整道题的难度——用调整法证明无关性,将复杂的过程问题退化为选根问题。

30
P3478 STA-Station
选做

题意nn 个节点的树。选一个节点作为根,使所有节点深度之和(根深度为 0)最大。输出该节点编号(多个输出任意)。

数据n106n \leqslant 10^6。时限 1s,内存 125MB。

Hint

换根 DP 模板。先任选根(如 1)DFS 得到初始深度和 dp[1]dp[1]。然后换根:当根从 uu 移到儿子 vv 时,vv 子树内所有点深度 -1,其余点深度 +1。dp[v]=dp[u]+n2×size[v]dp[v] = dp[u] + n - 2\times size[v]O(n)O(n)

31
选做

题意nn 个点的树,每个点颜色为白(1)或黑(0)。对每个点 vv,求包含 vv 的连通子图中,(白点数 - 黑点数)的最大值。

数据n2×105n \leqslant 2\times 10^5。时限 2s。

Hint

先自底向上 DP:Du=valu+vmax(0,Dv)D_u=val_u+\sum_v\max(0,D_v),其中 vv 枚举 uu 的儿子(valuval_u 为白 +1 黑 -1)。再换根:ansv=Dv+max(0,ansumax(0,Dv))ans_v=D_v+\max(0,ans_u-\max(0,D_v))O(n)O(n)

32
重点

题意nn 个节点的树。一步可以跳恰好 kk 条边(沿着树边跳)。求所有有序点对 (u,v)(u, v) 之间的最少跳跃次数之和。

数据n2×105n \leqslant 2\times 10^5k5k \leqslant 5。时限 2s。

Hint 1

模型分析

最少跳跃次数 =dist(u,v)/k= \lceil \operatorname{dist}(u, v) / k \rceil。直接求距离和是容易的,但不能简单除以 kk——因为上取整会破坏线性性。

Hint 2

按余数分类聚合

modk\bmod k 的余数分类!f[u][r]f[u][r] = uu 子树中到 uu 距离 r(modk)\equiv r \pmod{k} 的节点数。g[u][r]g[u][r] = 对应的最少跳跃次数之和。合并子树时向上传递。O(nk)O(nk)

启示

不能直接聚合的量 → 多分几类,按类分别聚合

33
P2607 骑士
普通

题意nn 个骑士,每人有一个"最讨厌的骑士" hih_i(可能讨厌自己)。每个骑士有战斗力 wiw_i。选出一个骑士集合,满足集合中没有人讨厌集合中的另一个人。求最大总战斗力。

数据n106n \leqslant 10^6wi106w_i \leqslant 10^6。时限 1s,内存 125MB。

Hint

每个人恰讨厌一个人 → 基环树(每个连通块恰有一个环)。在环上断一条边 (u,v)(u, v),做两次树形 DP:一次强制不选 uu,一次强制不选 vvdp[node][0/1]dp[node][0/1] 为不选/选该点的子树最大战斗力。O(n)O(n)

34
重点

题意:圆周上 nn 个点按顺时针编号 1n1 \sim n。给出 n×nn \times n 的 01 矩阵 aaa[i][j]=1a[i][j] = 1 表示 iijj 之间可以连线段(线段为弦)。求有多少种连边方案,满足:

  • 线段只能在端点上相交,不能交叉;
  • 最终图连通。 方案数对 109+710^9+7 取模。

数据n500n \leqslant 500。时限 2s。

Hint 1

模型分析

不允许线段交叉 → 连边的结构天然是"区间嵌套"的。即若 i<j<k<li < j < k < l,不可能同时有连边 (i,k)(i, k)(j,l)(j, l)

Hint 2

DP 对象是圆上区间

dp[l][r]dp[l][r] = 区间 [l,r][l, r] 内的点形成一个连通块的方案数(且最外层连接点必须是 llrr)。f[l][r]f[l][r] = 区间内任意合法连边方案数。

转移:dp[l][r]=k=lr1f[l][k]dp[k][r]dp[l][r] = \sum_{k=l}^{r-1} f[l][k] \cdot dp[k][r](枚举 rr 最左边的邻居)。f[l][r]=k=lr1f[l][k]dp[k][r]f[l][r] = \sum_{k=l}^{r-1} f[l][k] \cdot dp[k][r]O(n3)O(n^3)

启示

空间的几何限制可以转化为 DP 对象的递归结构。这题的"树"不是输入的一棵树,而是从圆的几何性质中推导出来的。

35
CF607B Zuma
普通

题意nn 个珠子排成一行,颜色分别为 cic_i。每次操作:可以消除一个回文子段(消除后两侧拼接)。求消除整个序列的最少操作次数。

数据n500n \leqslant 500cinc_i \leqslant n。时限 2s。

Hint

Dl,rD_{l,r} = 消除区间 [l,r][l, r] 的最少次数。若 cl=crc_l = c_r,可以"免费"把两边和内层一起消:Dl,rDl+1,r1D_{l,r}\gets D_{l+1,r-1}(注意当 l+1>r1l+1>r-1 时就是消掉两个相邻同色珠子)。否则枚举分割点:Dl,r=mink(Dl,k+Dk+1,r)D_{l,r}=\min_k(D_{l,k}+D_{k+1,r})O(n3)O(n^3)

36
P4170 涂色
普通

题意:长度为 nn 的木板初始无色。每次操作可以将一个连续区间涂成一种颜色(后涂覆盖先涂)。问最少几次操作能把木板变成目标颜色序列。

数据n50n \leqslant 50。时限 1s。

Hint

Dl,rD_{l,r} = 涂好区间 [l,r][l, r] 的最少次数。若 al=ara_l = a_r,则 Dl,r=min(Dl+1,r,Dl,r1)D_{l,r}=\min(D_{l+1,r},D_{l,r-1})——要么涂左边时顺便带右边,反之亦然。否则枚举分割点。与 Zuma 对称。O(n3)O(n^3)

37
普通

题意:给定一个合法括号序列。给每个括号染三种颜色之一:红、蓝、无色。限制:

  1. 每对配对括号恰有一个被染色;
  2. 相邻两个括号颜色不能相同。 求方案数,对 109+710^9+7 取模。

数据:序列长度(括号数)700\leqslant 700。时限 2s。

Hint

先预处理每个括号的配对位置 match[l]match[l]dp[l][r][cl][cr]dp[l][r][c_l][c_r] = 区间 [l,r][l, r] 两端颜色分别为 cl,cr{0,1,2}c_l, c_r \in \{0, 1, 2\} 的方案数。

r=match[l]r = match[l]llrr 配对),则内部区间 [l+1,r1][l+1, r-1] 独立处理;否则拆为 [l,match[l]][l, match[l]][match[l]+1,r][match[l]+1, r] 两段拼接。O(n2)O(n^2)

38
普通

题意:字符串的折叠表示:一段连续重复的字符串可以写为 次数(子串),如 ABCABC2(ABC)。数字和括号也计入长度(如 2(ABC) 长度为 5)。求给定字符串的最短折叠表示长度。

数据n100n \leqslant 100。时限 1s。

Hint

Dl,rD_{l,r} = 区间 [l,r][l, r] 的最短折叠长度。转移有两种:(1)枚举分割点拼接;(2)判断 [l,r][l, r] 能否由 [l,k][l, k] 重复若干次构成,若能则用 Dl,k+digit(cnt)+2D_{l,k}+\mathrm{digit}(cnt)+2 更新 Dl,rD_{l,r}cntcnt 为重复次数,括号贡献为 2)。O(n3)O(n^3)

39
P4767 邮局
选做

题意:数轴上有 nn 个村庄,坐标 aia_i 递增。选 kk 个村庄建邮局,每个村庄去最近的邮局。最小化所有村庄到其最近邮局的距离之和。

原题数据n3000n \leqslant 3000k300k \leqslant 300。时限 2s。

训练版建议:若尚未学习四边形不等式或决策单调性,建议将数据改为 n500, k100n \leqslant 500,\ k \leqslant 100,使用朴素 O(n2k)O(n^2k) 区间划分 DP;原题数据适合放到 DP 优化专题。

Hint

dp[i][j]dp[i][j] = 前 ii 个村庄建 jj 个邮局的最小距离和。一段村庄共享一个邮局时最优位置是中位数。

朴素转移枚举上一段起点,复杂度 O(n2k)O(n^2k),训练版做到这里即可。原题数据需要四边形不等式优化决策单调性,复杂度 O(nk)O(nk)

40
P3205 合唱队形
普通

题意:目标队形是一个序列 a1,,ana_1, \dots, a_nnn 个人的初始队伍为空,按某种顺序依次加入,每次新加入的人只能排在当前队伍的最左端或最右端。求有多少种加入顺序能形成目标序列 aa。对 1965082719650827 取模。

数据n1000n \leqslant 1000。时限 1s。

Hint

从最后一步往前想:最后一个插入的人一定在队伍的两端。dp[l][r][0/1]dp[l][r][0/1] = 区间 [l,r][l, r] 已形成且最后加入的是 ll(左边,0)还是 rr(右边,1)的方案数。根据与相邻元素的大小关系转移。O(n2)O(n^2)

41
重点

题意:初始空串。进行 nn 步,每步:在当前序列的某个随机位置插入一对括号 ()(均匀随机选择插入点)。求 nn 步后最终序列是合法括号序列的概率。对 998244353998244353 取模。

数据n500n \leqslant 500。时限 2s。

Hint 1

模型分析

有时间维度(每组括号"加入"的时间不同),直接按时间 DP 行不通:正着信息量太大,倒着会拆散同组括号。

Hint 2

找静态锚点:第一组括号

考虑第一组加入的括号(最早插入的)。在最终序列中,它们把序列切成三部分:左边的 ( 前面、两个括号之间、右边的 ) 后面。同组括号必在同一部分。

转化为求方案数:dp[i][j]dp[i][j] = 长度为 ii、当前前缀多余的 ( 数为 jj 的方案数。最后用概率公式还原。O(n3)O(n^3),卷积优化可至 O(n2)O(n^2)

启示

多维限制下,找一个不变的"锚点"作为递归拆分点

42
普通

题意:给定布尔函数 f(x,y,z)f(x,y,z) 的真值表(长度为 8 的 01 串,表示对 8 种输入 000~111 的输出)。求表示该函数的最短逻辑表达式。允许 AND(&)、OR(|)、NOT(!)、括号。优先级:括号 > NOT > AND > OR。有 tt 组询问。

数据t256t \leqslant 256(即最多 256 个不同的真值表)。时限 3s。

Hint

按表达式层级(优先级)BFS 递推。先算所有单字符表达式(x, y, z),然后逐层通过 NOT、AND、OR 组合出更复杂的表达式。对每个真值表记录最短表达式。O(t×8×28)O(t \times 8 \times 2^8)

43
P5658 括号树
普通

题意nn 个节点的有根树(根为 1),每个节点上有一个括号 ()。设 kik_i 为从根到节点 ii 的路径形成的字符串中,有多少个连续子串是合法括号序列。求 i=1n(iki)\bigoplus_{i=1}^{n} (i \cdot k_i)

数据n5×105n \leqslant 5\times 10^5。时限 1s,内存 256MB。

Hint

DFS 时维护一个栈(记录左括号的下标)。当遇到右括号时,若栈不空则弹出一个左括号,设它的下标为 pp,则 dp[u]=dp[fa[p]]+1dp[u] = dp[fa[p]] + 1(以 uu 结尾的合法子串数)。回溯时恢复栈。ku=kfa+dp[u]k_u = k_{fa} + dp[u]O(n)O(n)

44
P1896 互不侵犯
选做

题意n×nn \times n 棋盘上放 kk 个国王(攻击范围:周围 8 格)。国王之间不能互相攻击。求方案数。

数据n9n \leqslant 9kn2k \leqslant n^2。时限 1s。

Hint

状压 DP。预处理每行合法状态(没有相邻 1)及每种状态放置的国王数。再预处理两行间的兼容性。dp[i][mask][cnt]dp[i][mask][cnt] 逐行递推。合法状态远少于 2n2^n

45
P2704 炮兵阵地
选做

题意n×mn \times m 网格,部分格子是山(P,不可放)。炮兵攻击范围:上下左右各 2 格(共 4 方向 × 2 = 可达 12 格,但对称)。求最多能放多少个炮兵。

数据n100n \leqslant 100m10m \leqslant 10。时限 1s。

Hint

攻击范围跨两行 → 状态需记录前两行的部署情况。dp[i][S1][S2]dp[i][S_1][S_2] = 第 ii 行状态为 S1S_1、第 i1i-1 行状态为 S2S_2 时的最大炮兵数。滚动数组优化空间。O(n×3m)O(n \times 3^m) 或更优。

46
CF1215E Marbles
重点

题意nn 个珠子排成一列,颜色 ci20c_i \leqslant 20。每次操作交换相邻两颗珠子。求使所有同色珠子形成连续一段的最少交换次数。

数据n4×105n \leqslant 4\times 10^5ci20c_i \leqslant 20。时限 4s。

Hint 1

模型简化(核心!)

最终每种颜色的珠子是连续的一段 → 只需决定 20 种颜色的排列顺序。最少相邻交换次数 = 逆序对数。

Hint 2

换 DP 对象:从珠子到颜色

预处理 w[i][j]w[i][j] = 将颜色 ii 的所有珠子全部排在颜色 jj 的所有珠子前面时,颜色 iijj 之间的逆序对数(O(202n)O(20^2 n))。

dp[mask]dp[mask] = 已决定排列顺序的颜色集合为 maskmask(二进制),这些颜色排在其它颜色前面的最小逆序总和。转移:枚举下一个要排的颜色 kmaskk \notin mask,增加 jmaskw[j][k]\sum_{j \in mask} w[j][k]O(20×220)O(20 \times 2^{20})

启示

nn 很大但颜色很少 → DP 对象从"珠子"换成"颜色"。Step 2 的极致体现。

47
普通

题意nn 个点 mm 条边的无向图。求简单环的个数(不重复经过节点的环,长度 3\geqslant 3)。边集相同的环视为同一个。

数据n19n \leqslant 19mm 无特殊限制。时限 2s。

Hint

dp[mask][last]dp[mask][last] = 从 maskmask 中编号最小的点出发、以 lastlast 结尾、经过点集为 maskmask 的简单路径数。枚举下一个邻居扩展路径。当 lastlast 能连回起点且路径长度 3\geqslant 3 时计入答案。最终答案除以 2(每条环正反各算一次)。O(2nn2)O(2^n n^2)

48
普通

题意nn 个数 aia_i。对每个 aia_i,找一个 jij \neq i 使得 ai&aj=0a_i \And a_j = 0(即两个数的二进制表示无任何一位同时为 1)。若不存在输出 1-1

数据n106n \leqslant 10^6ai<222a_i < 2^{22}。时限 4s。

Hint

SOS DP(子集 DP)。dp[mask]dp[mask] = 任意一个"是 maskmask 的子集"的 aja_j 的值(若存在)。从低维向高维递推:dp[mask]dp[mask2i]dp[mask] \gets dp[mask \oplus 2^i](若 dp[mask]dp[mask] 为空且 dp[mask2i]dp[mask \oplus 2^i] 有值)。

对每个 aia_i,答案为 dp[ai&((122)1)]dp[\sim a_i \And ((1\ll 22)-1)]O(22×222)O(22 \times 2^{22})

49
普通

题意nn 个城市(编号 0n10 \sim n-1),有 mm 条无向边,每个城市有人口 wiw_i。将城市划分成若干州。一个州合法当且仅当:(1)州内城市构成连通块;(2)州内不存在欧拉回路。每个州的满意度为 (S/T)p(S/T)^p,其中 SS 是州内人口和,TT 是总人口和。求所有合法划分方案的总满意度,对 998244353998244353 取模。

数据n21n \leqslant 21m(n2)m \leqslant \binom{n}{2}p{0,1,2}p \in \{0, 1, 2\}。时限 10s。

Hint

子集卷积 + FWT。先判断每个子集 maskmask 是否是合法州:需检查连通性(只需两条及以上不交路径或度数判定)和欧拉回路存在性(每个点度数均为偶数)。

FM=SMFMSWSF_M=\sum_{S\subset M}F_{M\oplus S}\cdot W_S。按 popcount 分层,每层做 FWT(或 FMT),然后逐位做多项式乘法。O(n22n)O(n^2 2^n)

50
P1807 最长路
选做

题意nn 个点 mm 条边的 DAG(有向无环图),每条边有整数权值 ww(可正可负)。求从 1 到 nn 的最长路径长度。若 1 不能到达 nn,输出 1-1

数据n1500n \leqslant 1500m5×104m \leqslant 5\times 10^4105w105-10^5 \leqslant w \leqslant 10^5。时限 1s。

Hint

拓扑序 DP。初始化 dp[1]=0dp[1] = 0,其余为 -\infty。按拓扑序松弛:dp[v]=max(dp[v],dp[u]+w)dp[v] = \max(dp[v], dp[u] + w)。最后若 dp[n]=dp[n] = -\infty 则输出 1-1O(n+m)O(n+m)

51
CF919D Substring
普通

题意nn 个点 mm 条边的有向图。每个节点上有一个小写字母。一条路径的"价值"定义为该路径上出现次数最多的字母的出现次数。求最大路径价值。若图中有环(价值可无限大)则输出 1-1

数据n,m3×105n, m \leqslant 3\times 10^5。时限 3s。

Hint

先拓扑排序判环。dp[u][c]dp[u][c] = 以 uu 结尾的路径中,字母 cc 的最大出现次数。令 chvch_v 表示点 vv 上的字母,按拓扑序传递并更新 dp[v][c]=max(dp[v][c],dp[u][c]+[chv=c])dp[v][c] = \max(dp[v][c], dp[u][c] + [ch_v = c])O(26(n+m))O(26(n+m))

52
P1137 旅行计划
选做

题意nn 个点 mm 条边的 DAG。对每个点 ii,求以 ii终点的最长路径能经过多少个城市(包含起点和终点)。

数据n105n \leqslant 10^5m2×105m \leqslant 2\times 10^5。时限 1s。

Hint

拓扑序 DP。dp[v]=max(u,v)E(dp[u]+1)dp[v] = \max_{(u,v) \in E} (dp[u] + 1),初始所有 dp[i]=1dp[i] = 1O(n+m)O(n+m)

53
P3387 缩点
普通

题意nn 个点 mm 条边的有向图,每个点有权值 wiw_i。找一条路径(允许重复经过节点,但每个点的权值只算一次),求最大权值和。

数据n104n \leqslant 10^4m105m \leqslant 10^5wi1000w_i \leqslant 1000。时限 1s。

Hint

Tarjan 缩点(SCC)→ 得到 DAG,新点的权值为 SCC 内所有点权值之和。然后在新 DAG 上拓扑序 DP 最长路。O(n+m)O(n+m)

54
P2602 数字计数
选做

题意:给定两个正整数 a,ba, b。求 [a,b][a, b] 中每个数码 0~9 各出现了多少次。

数据1ab10121 \leqslant a \leqslant b \leqslant 10^{12}。时限 1s。

Hint

数位 DP 基础模板。从高位到低位逐位构造。状态:当前位 pospos、是否贴上限(limlim)、是否有前导零(leadlead)。记忆化搜索,O(10×log10b×2×2)O(10 \times \log_{10} b \times 2 \times 2) 每种数码一次。

55
P2657 windy 数
选做

题意:不含前导零且任意相邻两个数码之差的绝对值 2\geqslant 2 的正整数称为 windy 数。求 [a,b][a, b] 中有多少个 windy 数。

数据1ab2×1091 \leqslant a \leqslant b \leqslant 2\times 10^9。时限 1s。

Hint

比模板多一维:dp[pos][pre]dp[pos][pre] = 当前位为 pospos、上一位填了 prepre 时的方案数(不含贴上限和前导零的情况)。转移时检查 curpre2|cur - pre| \geqslant 2

56
CF628D Magic Numbers
普通

题意:定义 dd-magic 数:在偶数位置上的数码必须是 dd,在奇数位置上的数码不能是 dd(位置从 1 开始,1 为最高位),且无前导零,且整个数字能被 mm 整除。求区间 [L,R][L, R]dd-magic 数的个数,对 109+710^9+7 取模。

数据L,R2000|L|, |R| \leqslant 2000(即数字最多 2000 位),m2000m \leqslant 20000d90 \leqslant d \leqslant 9。时限 2s。

Hint

多一维"当前数字 modm\bmod m 的余数"。状态:dp[pos][rem][lim][lead]dp[pos][rem][lim][lead]。根据当前位置的奇偶性决定合法数码集合。O(R×m×10)O(|R| \times m \times 10)

57
P3193 GT 考试
重点

题意:求有多少个 nn 位十进制正整数(无前导零),其十进制表示中不包含子串 SSSS 为给定的非空数字串)。对 kk 取模(kk 不一定是质数)。

数据n109n \leqslant 10^9S=m20|S| = m \leqslant 20k1000k \leqslant 1000。时限 1s。

Hint 1

KMP 自动机

SS 的 KMP 自动机(即 nextnext 数组 + 转移表)。状态为当前在自动机的哪个节点(即已匹配 SS 的前几个字符)。

Hint 2

矩阵快速幂优化

由于 n109n \leqslant 10^9,不能逐位递推。注意到转移是线性且状态数少(mm),写出转移矩阵 AAAi,jA_{i,j} = 从状态 ii 经过填一个数码后到达状态 jj 的方案数),用矩阵快速幂 O(m3logn)O(m^3 \log n)

注意:状态 mm(匹配完整个 SS)是非法状态,转移矩阵中要排除。

启示

发现转移是线性的 → 矩阵快速幂将 O(n)O(n) 降到 O(logn)O(\log n)。Step 4 最经典案例。

58
P1077 摆花
选做

题意nn 种花共摆 mm 盆,第 ii 种最多 aia_i 盆。同种花必须放一起,且按种类编号从小到大排列。求方案数,对 106+710^6+7 取模。

数据n,m100n, m \leqslant 1000ai1000 \leqslant a_i \leqslant 100。时限 1s。

Hint

多重背包求方案数。dp[i][j]dp[i][j] = 前 ii 种花放 jj 盆的方案数。dp[i][j]=k=0min(ai,j)dp[i1][jk]dp[i][j] = \sum_{k=0}^{\min(a_i, j)} dp[i-1][j-k]。滚动数组 + 前缀和优化:dp[j]=sum[j]sum[jai1]dp[j] = sum[j] - sum[j-a_i-1]O(nm)O(nm)

59
普通

题意nn 件商品,第 ii 件需要 tit_i 秒扫描,价格 cic_i。收银台在扫描某件商品时,在接下来 tit_i 秒内,其他商品若无防盗标签,可以被偷走。你需要决定为哪些商品购买防盗标签(买了标签的商品不会被偷,价格为 cic_i),使得所有 nn 件商品都安全。求最小花费。

数据n2000n \leqslant 2000ti2000t_i \leqslant 2000ci109c_i \leqslant 10^9。时限 1s。

Hint

转化:扫描第 ii 件商品相当于"覆盖"了 ti+1t_i + 1 个位置(它自己 + 它保护的后 tit_i 件)。dp[j]dp[j] = 获得至少 jj 单位"覆盖"的最小花费。做"至少"背包:dp[j]=min(dp[j],dp[jti1]+ci)dp[j] = \min(dp[j], dp[j - t_i - 1] + c_i)jj 从大到小,且可超出 nnO(n2)O(n^2)

60
CF1442D Sum
重点

题意:有 nn非递减数组(第 ii 个长度为 lil_i)。你需要选恰好 kk 个元素,限制:对每个数组只能选它的一个前缀(可以为空)。求最大总和。

数据n,k3000n, k \leqslant 3000li106\sum l_i \leqslant 10^6。时限 2s。

Hint 1

模型性质挖掘

关键性质:至多一个数组会"部分选"(选了前缀但没选完)。因为所有数组都是非递减的,拿后面的数只会更大,如果某个数组选了但没选完,不如再从那拿一个替代另一个数组的。

Hint 2

分治处理

分治确定哪个数组"部分选"。递归到区间 [L,R][L, R] 时,强制这个范围内的某个数组可能是部分选的。通过分治过程中的背包合并,保证只有当前区间外的数组被"全部选完或全部不选"。O(nklogn)O(nk \log n)

61
CF1740F Conditional Mix
普通

题意:给定一个多重集 a1,,ana_1, \dots, a_n(可能有重复)。你可以把 aa 划分成若干组(组间无序)。问能生成多少种不同的多重集,其中"不同"是指"每组大小"的分布(即 {size1,size2,}\{size_1, size_2, \dots\} 组成的多重集)不同。

数据n2000n \leqslant 2000。时限 2s。

Hint

逐种大小 DP(不是逐个元素!)。cnt[x]cnt[x] = 数值 xx 的出现次数。prek=min(cnt[i],k)pre_k = \sum \min(cnt[i], k) = 前 kk 大的组最多能容纳多少个元素。dp[i][j]dp[i][j] = 确定了最大的 ii 种 size、总共放了 jj 个元素的方案数。状态数 O(n2logn)O(n^2\log n)。转移 O(1)O(1)(新加一种 size 或全体 +1)。对 998244353998244353 取模。

62
重点

题意:给定 nn 个正整数 aia_i 和两个整数 L,RL, R。求有多少个 b[L,R]b \in [L, R] 可以表示为 kiai\sum k_i \cdot a_ikik_i 为任意非负整数,即每个物品无限取用)。

数据n12n \leqslant 12ai5×105a_i \leqslant 5\times 10^5L,R1012L, R \leqslant 10^{12}。时限 1s。

Hint 1

模型分析

L,R1012L, R \leqslant 10^{12} 太大,逐容量 DP 不可行。需要换一个视角。

Hint 2

最激进的重定义:从容量到余数

取最小的 aa(设为 a0a_0),按 moda0\bmod a_0 的余数分类。dis[r]dis[r] = 模 a0a_0rr最小可达值(即最小的能表示为 kiai\sum k_i a_ir(moda0)\equiv r \pmod{a_0} 的数)。

建图:对每个余数 rr 和每个 aia_i,连边 r(r+ai)moda0r \to (r + a_i) \bmod a_0,权 aia_i。跑 Dijkstra 最短路求 disdis

最后统计:对每个余数 rr,区间 [L,R][L, R]dis[r]\geqslant dis[r]r(moda0)\equiv r \pmod{a_0} 的数的个数。O(na0loga0)O(n a_0 \log a_0)

启示

DP 对象从"容量"变成"余数"——Step 2 中最激进的重定义。同余最短路。