动态规划泛做
CF833B The Bakery
令 \(f_{i,j}\) 表示前 \(i\) 个数字分成 \(j\) 段的最大总价值,转移方程 \(f_{i,j}\gets\max\{f_{i,l-1}+\operatorname{kind}(l,j)\}\),其中 \(\operatorname{kind}(l,j)\) 表示区间 \([l,j]\) 中不同的数字种类。
直接暴力转移是 \(O(n^2k)\) 的。考虑把 \(\operatorname{kind}\) 函数拆开优化,将每种数字的贡献对应到区间中该种数字第一次出现的位置。对于数字 \(a_i\),其对 DP 数组中 \([last_i,i)\) 的区间产生了 \(1\) 的贡献,其中 \(last_i\) 表示 \(a_i\) 上一次出现的位置。
先枚举段数 \(k\),再枚举位置。用线段树维护上一轮 DP 数组加上当前已有转移的贡献,前缀 \(\max\) 即为 DP 值。
CF449D Jzzhu and Numbers
不好统计按位与等于某个值的方案数,就先统计按位与包含某个值的方案数,即按位与在该值超集中的方案数,然后差分回去(做系数为 \(-1\) 的高维超集前缀和)。
对于按位与包含某个值的方案,不包含该值的不能选,包含该值的可选可不选,但至少选一个。所以总方案数是 \(2\) 的该值超集和次幂减 \(1\)。
CF123E Maze
先考虑起点和终点固定怎么做,代码会从起点开始依次经过到终点路径上的每一条边。假设当前在 \(u\) 准备通过 \((u,v)\) 走到 \(v\),那么对于在 \((u,v)\) 前面的每条边 \((u,v')\),代码都会先进入并遍历完以 \(v'\) 为根的子树。因为出点的顺序是随机打乱的,所以每条边在 \((u,v)\) 前面的概率都是 \(\frac{1}{2}\),在后面则不会遍历。
分析一下伪代码:搜下去并返回会加 \(2\) 次,所以不在路径上的边贡献均为 \(2\times\frac{1}{2}=1\);而在路径上的边必定会遍历,但不会返回,贡献也为 \(1\times 1=1\)。这样问题就转化成了以起点为全树的根,去掉以终点为根的子树,剩下边(点)的期望数量。
计算的重点在于终点,所以随便钦定一个点为全树的根,枚举终点,分起点在子树中或子树外讨论即可。
P1285 队员分组
将非互相认识的两人连边,这样没有边相连的两人就可以放进同一组,所以连通块是独立的。对每个连通块都跑一遍二分图染色,算出该连通块中两组的人数,一旦出现冲突就无解。最后跑一遍带方案的必选背包。
P2519 「HAOI2011」problem a
如果 \(a_i+b_i\geq n\),那么第 \(i\) 个人一定在说假话,否则说明 \((b_i,n-a_i]\) 这段排名区间中的人成绩是相同的,并且这种成绩也仅出现在这段排名区间中。
把相同的区间合并,注意人数大于区间长度时多出来的人一定在说假话,要取个 \(\min\)。问题转化成了选择若干个互不相交的区间使得总人数最多,在排名区间上 DP 即可。
P2476 「SCOI2008」着色方案
\(c\) 很小可以记入状态,令 \(f_{a,b,c,d,e,last}\) 表示还能涂 \(1/2/3/4/5\) 个木块的颜色有 \(a/b/c/d/e\) 种,上一次涂的颜色现在还能涂 \(last\) 个的方案数。
倒序枚举 \(e\to a\),如果 \(last\) 和当前准备涂的颜色还能涂的个数相同,那么乘的时候为了相邻颜色不同能填的种数要减 \(1\)。
其实没必要按木块顺序依次涂色,完全可以按颜色顺序用插入的形式转移。令 \(f_{i,j}\) 表示当前涂了 \(i\) 个木块,有 \(j\) 处相邻同色木块还需要被插入的方案数。
主动转移,枚举当前颜色分成的段数 \(a\) 和其中插入相邻同色木块的段数 \(b\):
三个组合数分别是用隔板法算当前颜色分段方案数、插入相邻同色木块方案数、插入相邻不同色木块方案数。
P2523 「HAOI2011」Problem c
容易发现人入座的顺序是无关的,只需要考虑编号,有解的条件是每个后缀中的编号数量不能超过后缀长度。
因为较短的后缀会影响到较长的后缀,所以从后往前 DP。令 \(f_{i,j}\) 表示大于 \(i\) 的编号已经确定,其中安排了 \(j\) 个没有贿赂上司的。
转移枚举当前编号 \(i\) 安排的数量 \(k\),现在还有 \(n-m-j\) 个人没有确定编号,注意虽然人顺序无关但人还是不同的要乘上组合数:
CF559C Gerald and Giant Chess
棋盘很大不能直接 DP,黑色格子也较多不能直接容斥,那就需要在每种合法或不合法方案的特定位置进行计算。
先排序,确保只有前面的格子能转移到后面的格子。令 \(f_i\) 表示从起点 \((1,1)\) 走到第 \(i\) 个黑色格子,不经过其它黑色格子的方案数。转移就拿不考虑前面黑色格子的总方案数减去上一次从黑色格子走过来的方案数。
这样对于任意一条不合法的路径,我们都在且仅在它经过的第一个黑色格子那里减掉了,不重不漏。
CF567F Mausoleum
发现从 \(n\to 1\) 将数依次放在两侧即可保证单峰。但限制跟下标有关,所以必须考虑绝对位置。
区间 DP,每次放两个相同的数,分全在左边/一左一右/全在右边三种情况讨论,如果所有位于当前区间内的限制都满足则合法。
CF590D Top Secret Task
交换次数这么大显然是无用的,最坏情况只是把后半部分的数顺次移到前半部分而已,仅需要 \(\frac{n}{2}\times\frac{n+1}{2}\) 次。
所以完全可以把交换次数记入状态。令 \(f_{i,j,p}\) 表示前 \(i\) 个数进行顺次交换已经确定了前 \(j\) 个数,交换次数至多为 \(p\) 的最小和:
从大到小枚举 \(j\) 可以把第一维去掉。
CF37D Lesson Timetable
先不考虑初始教室中小组的编号,最后再将答案乘上 \(\dfrac{(\sum x)!}{\prod x!}\)。所以只需要考虑每一组移动到了哪里,记录前面有几组移动到了后面去。
但是这样记录其实是不太好写的,因为移动的组数会根据当前教室原组数与新组数的相对大小非单调变化,所以直接记录绝对组数再用总和去减会好写一点。
同时倒序做会存在一个问题,当前教室剩下的组是不能参与前面的转移的,而我们无法确定有几组已经移动到后面去了,这样当前教室能从前面移过来几组也是不知道的。
所以只能正序转移,令 \(f_{i,j}\) 表示前 \(i\) 间教室最终存在 \(j\) 组的方案数:
P5851 「USACO19DEC」Greedy Pie Eaters P
如果只考虑选哪些奶牛吃派和奶牛吃派的顺序,就会陷入僵局,我们不妨考虑派的情况。
令 \(f_{i,j}\) 表示 \(i\sim j\) 这一段派满足一些奶牛,它们的最大可能体重。因为一头奶牛至少吃一个派,所以转移可以枚举区间内最后吃的这头奶牛吃的某个派 \(k\)。前提是这头奶牛不会吃 \(i\sim j\) 范围外的派:
直接枚举 \(p\) 是 \(O(N^3M)\) 的。容易发现固定 \(i,j,k\) 可以预处理出最大的 \(w_p\) 去掉 \(M\)。

浙公网安备 33010602011771号