2024.1.12 fxj(原 zjk)DP 专题
2024.1.12 fxj(原 zjk)DP 专题
GYM102904B Dispatch Money
题意
长度为 \(n\) 的排列,将其分段,每段的代价为逆序对数加 \(k\),求最小代价和。
\(n \le 3 \times 10^5\)。
分析
逆序对数是很经典的有决策单调性的区间权值,考虑分治优化 dp。
由于是在线转移,考虑使用 CDQ 解决,如果用莫队维护逆序对数,根据整体二分经典结论:指针移动次数 \(\mathcal O(n\log^2 n)\)。
用 BIT 维护,总复杂度 \(\mathcal O(n\log^3 n)\),可以通过。
Code
提交记录:https://codeforces.com/gym/102904/submission/241255308。
GYM102331J Jiry Matchings
题意
给定 \(n\) 个点的带边权树,对 \(k = 1 \sim n - 1\),求大小为 \(k\) 的最大匹配。
\(n \le 2 \times 10^5\)。
分析
考虑朴素 dp,设 \(f_{u, i, 0/1}\) 表示 \(u\) 为根的子树,匹配了 \(i\) 组,是/否匹配了 \(u\) 的最大权值。
由于二分图最大权匹配显然是费用流可解问题,所以该 dp 具有凸性,可以 \(\mathcal O(sz)\) 的合并两个背包,这启示我们可以类全局平衡二叉树分支合并,可以做到复杂度 \(\mathcal O(n\log n)\)。
实现不精细的通过树剖优化的 dp 可以做到 \(\mathcal O(n\log^2 n)\),也可以通过,给出该实现。
Code
提交记录:https://codeforces.com/gym/102331/submission/241414033。
HDU6094 Rikka with K-Match
题意
\(n \times m\) 的带边权网格图,求大小为 \(k\) 的最小权匹配权值。
\(n \le 5 \times 10^4, m \le 4\)。
分析
朴素 dp 设 \(f_{i, j, s}\) 表示考虑到第 \(i\) 行,匹配了 \(j\) 条边,上一行匹配的状态为 \(s\) 的最小权值。
该问题显然具有凸性,考虑使用 wqs 二分优化朴素 dp,注意转移顺序。
时间复杂度 \(\mathcal O(nm2^m\log v)\)。
Code
提交记录:https://paste.ubuntu.com/p/qk9qzSS6F4/ 或 http://www.gdfzoj.com:23380/submission/369741。
GYM102268J Jealous Split
题意
给一个长度为 \(n\) 的非负整数序列 \(a\),你需要将其划分成 \(k\) 段。定义第 \(i\) 段的和为 \(s_i\),最大值为 \(m_i\),你的划分方案需要满足 \(\forall i \in \{1, 2, \dots, n\}, |s_i − s_{i+1}| \leq max(m_i, m_{i+1})\)。
构造一个方案或输出无解。
\(3 \leq k \leq n \leq 100\,000\), \(0 \leq a_i \leq 50\,000\)。
分析
如果出现非法状态,显然可以将和大的一边分一点向小的一边,这下我们可以确定对于最有分组方式有 \(s_i^k + s_{i + 1}^k\) 取到最小值,取 \(k = 2\),可以通过 wqs 二分求解。
但是注意到 wqs 二分不能精准控制段数,只能找出上下界,这个时候要在保证满足四边形不等式约束的前提下在相邻位置调整,即找到一个 \(p_i < q_j \land q_{j + 1} < p_{i + 1}\) 的决策点。
复杂度 \(\mathcal O(n \log v)\)。
Code
提交记录:https://codeforces.com/gym/102268/submission/241522520。
[CTS2021] 数组
题解
求在满足 \(a_i \times a_{i + 1} \ge b_i\) 的前提下 \(\sum a_i\) 的最小值,注意 \(a_i \in \mathbb{R}^*\)。
\(n \le 3000, b_i \le 4000\)。
分析
考虑全程乘积对 \(b_i\) 要么取等,要么大于(且不连续),不然就太亏了,显然可以通过调整变更小。
那么对于一段取等的连续段,设左端点为 \(v\),那么最后的和一定形如 \(pv + \dfrac{q}{v}\),拿最小值和两端点处的值就都知道了。
现在考虑连接处,你既然都大于了,那两边不去到最优就太亏了,所以就能 dp 了,设 \(f_{i, j}\) 表示最后一段填的是 \([i, j]\) 的最小和,显然这是离线 dp 问题,可以通过前缀 \(\min\) 加二分最优决策点做到 \(\mathcal O(n^2\log n)\)。
Code
提交记录:https://paste.ubuntu.com/p/XySGc73Z9R/ 或 http://www.gdfzoj.com:23380/submission/369947。
「ZJOI2019」麻将
题解
一副麻将是胡的当且仅当达成以下两个条件之一:
- 存在一个对子,三个面子;
- 存在不相同的七个对子。
有 \(n\) 种牌,每种 \(4\) 张,给定前 \(13\) 张,求胡牌需要的期望轮数。
\(n \le 100\)。
分析
考虑将一个状态转换成每种花色 \(i\) 抽到了 \(a_i\) 张,那么如何对它 dp 检测是否胡牌呢?我们设 \(f_{i, j, k}\):考虑到 \(i\),钦定有 \(j\) 组 \((i - 1, i)\),有 \(k\) 张 \(i\) 的最多面子数。为了以防形成考虑之外的面子,\(j, k < 3\)。
显然转移与 \(i\) 无关,考虑将转移的 DFA 建出来,进行 dp 套 dp,设 \(f_{i, j, k}\):前 \(i\) 中花色,走到节点 \(j\),用了 \(k\) 张牌的方案数。由于状态数 \(m = 2092\) 很小,所以暴力转移即可。
最后统计答案在非胡牌节点统计每种概率之和即可。
复杂度 \(\mathcal O(n^2m)\)。
Code
提交记录:https://loj.ac/s/1977794。
CF1456E XOR-ranges
题意
有序列 \(\{a_n\}\),\(a_i\) 在 \([l_i, r_i]\) 中自由选取,\(r_i < 2^k\),给定每个二进制位的代价 \(c_i\),求 \(\sum \operatorname{cost}(a_i \bigoplus a_{i - 1})\) 的最小值。
\(n \le 50, k \le 50, c_i \le 10^{12}\)。
分析
显然可以将贡献拆到每一位算,考虑数位 dp,观察当限制被打破时可能出现的现象。
考虑第 \(i\) 位,对于序列 \(\{a_n\}\),若 \(a_{2 \sim n - 1}\) 此时已不受限制,则这一位的贡献 \(\operatorname{cost}(a) = \operatorname{cost}(a_1 \bigoplus a_n)\)(显然可以令 \(\forall 1 < i < n, a_i = a_1\))。设 \(h_i\) 为 \(a_i\) 打破限制的二进制位(从低到高),这说明:从高到底考虑(当前到 \(i\)),\(h_j \le i\) 的位置将会把一整段分为若干小区间,而第 \(i\) 位的贡献之和这些位置有关。
在上面限制的前提下就可以考虑区间 dp,设 \(f_{i, l, r, 0/1, 0/1, 0/1, 0/1}\) 表示考虑到二进制位 \(i\),目前解决的是 \([l, r]\) 这个子问题,钦定 \(h_{l - 1}, h_{r + 1} \le i\),且 \(a_{l - 1} / a_{r + 1}\) 顶上/下界,第 \(i\) 位是/否要取反(取反说明 \(h_j = i\))。
转移分两部分:
-
不存在分界点:\(i \gets i - 1\);
-
存在分界点:枚举分界点 \(l \le j \le r\),\((l, r) \gets (l, j - 1) + (j + 1, r)\),具体的还要枚举 \(h_j\) 是否等于 \(i\)。
复杂度 \(\mathcal O(n^3k)\)。
Code
提交记录:https://codeforces.com/contest/1456/submission/241557855。
HDU5121 Just A Mistake
题意
给定一颗 \(n\) 个点的树,对于所有 \(1 \sim n\) 的排列,依次加入 \(p_i\) 并维护独立集,求独立集大小的和模 \(10^9 + 7\) 的值。
\(n \le 200\)。
分析
考虑设 \(f_{u, i}\) 表示已 \(u\) 为根,\(u\) 在子树中排名为 \(i\),\(u\) 必选的方案数。
考虑枚举儿子 \(v\),要求 \(v\) 必须在 \(u\) 之后被选,组合数计算法案即可。
Code
提交记录:https://paste.ubuntu.com/p/658pr2gdRf/ 或 http://www.gdfzoj.com:23380/submission/369887。
TopCoder 11779 Pikachu
题意
存在三种字符,它们的代价分别是 \(\{2, 2, 3\}\),用它们拼出 \(n\) 个字符串,且 \(\not \exist i, j, s_i \text{ is preffix of } s_j\),最小化 \(\sum a_i c_i\),其中 \(c_i\) 位选用的字符的代价之和,\(a_i\) 由输入给定,并求出方案数模 \(10^9 + 7\)。
\(n \le 30\)。
分析
考虑用这三种字符建出一个特殊的字典树,定义一个节点的层数为 \(c_i\)。
显然每一层的节点要么形成我选用的字符串,要么向下延展,所以只需要接下来三层的点数就可以表示当前的状态。
所以考虑 \(f_{i, a, b, c}\) 表示已经使用 \(i\) 个节点,当前层,下一层,下下层的节点数为 \(a, b, c\)。
注意计算贡献可以考虑有多少个点将跨过当前这一层,即枚举这一层放 \(j\) 个点,贡献为 \(n - i - j\)。
复杂度 \(\mathcal O(n^5)\)。
Code
提交记录:https://paste.ubuntu.com/p/RVhxGjHrYn/ 或 http://www.gdfzoj.com:23380/submission/370377。
GYM102155B Short Random Problem
题意
给你一棵由 \(n\) 个顶点组成的树,每条边的长度是一个实数,在 \(0\) 和 \(1\) 之间独立均匀地随机选择,求这棵树的直径的期望值。
\(n \le 100\)。
分析
先简化问题,如果枚举直径中点在那一条边 \((u, v, w)\) 上(不妨假设 \(d_u < d_v\)),则需满足 \(d_v < \dfrac{d_u + d_v + w}{2} < d_u + w\),就是 \(d_v < d_u + w\),这样的话就具体化到了两边的最大深度。
考虑概率累计函数 \(F(x) = P(D \le x)\),表示当前树的最大深度,那么在此基础上加一条边(相当于从儿子转移至父亲)就有 \(G(x) = \displaystyle\int_0^1 F(x - t)dt\)。
考虑这个函数的性质:
- 对于任意树的形态,\(F(x)\) 是一个分段的有限多项式(产生性的段的原因是 \(x - t\) 属于上一段或不存在);
- \(F^\prime(x)\) 为 \(P(x = D)\) 的概率密度;
- \(\displaystyle\int_{-\infty}^{\infty}(1 - F(x))dx = E(D)\)。
设 \(F(x) = f_i(x - (i - 1)) \ (i - 1 \le x \le i)\),考虑怎么计算转移:转移相当于 \([x - 1, x]\) 这一部分的面积,但是有一部分在前一段,考虑容斥,变成总面积减 \([i - 2, x - 1]\) 的部分。具体的 \(g_i(x) = \displaystyle{\int (f_i(x) - f_{i - 1}(x))dx + \int_0^1f_{i - 1}(x)dx}\)。
最后统计答案的时候可以分成 \(E(d_u)\) 在减去 \(d_u + w < d_v\) 的 \(d_u\) 的期望,右侧 \(E(d_v)\) 同样计算,具体的:
复杂度 \(\mathcal O(n^4)\)。
Code
提交记录:https://codeforces.com/gym/102155/submission/241864849。
P8497 [NOI2022] 移除石子
题意
有 \(n\) 堆石子,第 \(i\) 堆有 \(a_i\) 枚,通过如下操作将所有石子移除:
- 选择 \(i\),一处至少 \(2\) 枚石子;
- 选择区间 \([l, r]\),满足区间长度至少为 \(3\),令 \(\forall i \in [l, r], a_i \gets a_i - 1\)。
给定 \(n, \{l_n\}, \{r_n\}\),求有多少中不同的满足 \(a_i \in [l_i, r_i]\) 的 \(\{a_n\}\),在任意加入恰好 \(m\) 个石子后能被完全移除,答案对 \(10^9 + 7\) 取模。
\(T \le 10, n \le 1000, r_i \le 10^9, m \le 100\)。
分析
考虑如何判断一个 \(\{a_n\}\) 能否被移除。
简化题意,先假设 \(k = 0\):设计 \(f_{i, j, k}\) 表示考虑 \(1 \sim i\),钦定 \(j\) 个二操作至少延伸到 \(i\),\(k\) 个操作至少延伸到 \(i + 1\),是否可行。转移要枚举以这一位为终点和起点的二操作分别有多少个,设有 \(l\) 个以 \(i\) 为起点,则要求 \(a_i - j - k - l \in \{x | x = 0 \lor x \ge 2\}\)。需要优化。
注意到:
- 不可能出现相同的二操作,否则可以用一操作代替;
- 操作区间长度只能为 \(\{3, 4, 5\}\) 否则可以分裂为更小的区间的共同效果。
所以:
-
每个点出发的区间数小于等于 \(3\),即 \(l \le 3\),所以 \(k \le 3\);
-
到 \(i\) 时长度已达 \(3\) 的区间只有:起点 \(i - 2\) ,长度为 \(3, 4, 5\);起点 \(i - 3\),长度为 \({4, 5}\);起点 \(i - 4\),长度为 \(5\);共 \(6\) 种,即 \(j \le 6\)。
进一步的优化发现:同时出现 \(4, 5\) 是可以用一次一操作和 \(3, 4\) 代替,所以 \(j \le 4, k \le 2\)。
但是直觉上觉得选择这么多二操作,可能出现大量浪费,不如用一操作代替,经过分类讨论,发现实际上 \(j \le 2, k \le 2\) 即可。
讨论加入 \(k\) 的情况:我们可以通过 dp 算出需要的石子数的下界,所以我们很希望能将恰好弱化为至多。
讨论:
-
\(k = 1\),讨论不加入石子时有解的局面:
- 出现一操作,把该石子在这个操作中一同去掉即可;
- 有长度大于 \(3\) 的二操作,拆成一次操作去掉端点和额外石子和一次长度减一的二操作;
- 有二操作且 \(n > 3\),考虑延伸这个二操作。
综上,只有当不存在操作(全零)或 \(a = \{1, 1, 1\}\) 时会矛盾,特判掉就行。
-
\(k > 1\),分类讨论:
- 若 \(k = 0\) 时有解,则用一次一操作将额外的全部消除;
- 若 \(k = 1\) 时无解,不可能由某个局面加入 \(k - 1\) 个石子后由有解变为无解。
综上特判 \(\{0, 0, \dots\}, \{1, 1, 1\}\) 即可完成弱化。
将状态改为最小的额外石子数即可,转移的时候考虑设 \(v = a_i - j - k - l\),那么贡献 \(w = \cases{-v & v < 0 \\ 1 & v = 1 \\ 0 & otherwise}\)。复杂度 \(\mathcal O(n\prod (r_i - l_i + 1))\),代码:https://uoj.ac/submission/673513。
\(k = 0\) 的部分还启发我们进行 dp 套 dp,不难发现当 \(a_i > j + k + l\) 时本质相同,也就是说 \(8 \sim \infty\) 可以认为是同一种状态,我们考虑建出 DFA 进行转移,复杂度 \(\mathcal O(nS)\),\(S\) 为状态数,大概级别不超过 \(2^9\)。
我们尝试将其搬到 \(k > 0\) 上,\(S\) 的理论上界达到 \(102^9\)(\(0 \sim 100\),和无解),但是不难由贡献的形式感受到同一状态的九个值不会相差很大,实际上 \(S = 8765\),可以通过。
复杂度 \(\mathcal O(nS)\)。