2025.3.27 DP综合

A CF1920E Counting Binary Strings

挺简单的一道 DP。

我们发现,原串一定是形如 \(0 \ldots 010 \ldots 0 1 \ldots 1 0 \ldots 0\) 的,设一个 \(1\) 左右两边分别有 \(L,R\)\(0\),则这个 \(1\) 对好的子串的总和的贡献是 \((L + 1)(R + 1)\)

发现我们只关心连续的 \(0\) 的长度,则我们可以将所有连续 \(0\) 的长度转为一个数组 \(a\),则题目的约束可以转化为 \(\begin{cases} \sum _ {i = 1} ^ {|a| - 1} (a _ {i} + 1) (a _ {i + 1} + 1) = n \\ \forall i \in [1,|a|),a _ {i} + a _ {i + 1} \le k - 1 \end{cases}\)

所以,我们就可以设 \(dp _ {i,x}\) 表示有 \(i\) 个好的子串,\(a\) 最后一位是 \(x\)。则转移就是枚举上一位的值 \(y\),从 \(dp _ {i - (x + 1)(y + 1),y}\) 转移过来,即 \(dp _ {i,x} = \sum _ {y \le k - 1 - x \wedge (x + 1)(y + 1) \le i} dp _ {i - (x + 1)(y + 1),y}\)

因为 \((x + 1)(y + 1) \le i \wedge y \le k - 1 - x\),所以 \(y\) 的上界是个反比例函数,时间复杂度应该是 \(\Omicron(n ^ 2 \ln n)\) (?瞎算的,反比例函数的积分是自然对数,一只邦布说是 \(\Omicron(n ^ {2.5})\),但是好像不对)

B CF1913D Array Collapse

二次原。

D CF1906J Count BFS Graph

根据题面给的代码,发现一个节点放进数组的数一定是单调递增的,于是我们可以预处理 \(nxt _ i\) 表示 \([i + 1,nxt _ i - 1]\) 是单调递增的极长区间。

\(dp _ {i,j}\) 表示考虑到 \(a _ i\)\(a _ j\) 与之前的已经被 BFS 过了。则 \(dp _ {i + 1,j} = \sum _ {k \le j \lt nxt _ k} 2 ^ {k - i} dp _ {i,j}\)

直接做是 \(\Omicron(n ^ 3)\) 的,发现后面是个区间和,考虑用前缀和优化,复杂度变为 \(\Omicron(n ^ 2)\)

E CF1900E Transitive Graph

简单题,可能因为缩点评到 2100?

我们发现,路径权值只和点权有关,和边无关,并且我们必须到达尽量多的点。并且,如果存在 \(a \to b,b \to c\),虽然会加一条 \(a \to c\),但是我们为了满足数量最多,也不可以略过 \(b\),所以题目加的边是没用的。

然后我们发现,原图是个有环图,没有一个比较好的拓扑结构供我们 DP。我们发现,一个环内的点你无论如何都得全部取,所以我们可以直接跑 SCC Tarjan,缩完点之后在拓扑排序时 DP,设 \(dp _ {u}\) 表示到点 \(u\) 的最长路径长度和最小权值,可以直接用 pair<int,int> 存下来一起更新。则我们每次就可以用 \(dp _ {u} + \{num _ v,sum _ v\}\) 去尝试更新 \(dp _ v\),顺便用同样的方式更新答案。

posted @ 2025-03-27 20:38  xguagua_233  阅读(30)  评论(0)    收藏  举报