CCPC 2023 北京市赛

发布时间 2024-01-08 10:43:56作者: came11ia

比赛链接

A. 游戏

显然走回头路不优,于是可以直接 DP,如果有 \(\geq 2\) 个儿子能赢那 \(u\) 就能赢。

B. 替换

没啥意思的题。一开始想的根号分治,但是发现 \(\geq B\) 的部分只会用 bitset 暴力,然后写一下发现直接过了,有点无语。

C. 史莱姆工厂

区间 DP,考虑最后一步删的是原序列中的哪些,发现一定是一个子序列,满足其能够分成两个 \(< k\) 的部分,并且总和 \(\geq k\)

因此可以设 \(f_{l,r,c,p,q}\) 表示考虑区间 \([l,r]\),最后一步删的是颜色 \(c\),第一个部分和为 \(p\),第二个部分和为 \(q\) 的答案,\(g_{l,r}\) 表示区间 \([l,r]\) 的答案,容易写出转移。转移的时候需要满足子序列划分出的每一段中最后一步删的颜色不能是 \(c\),判一下就行了。合并 \(p,q\) 的代价 \(h_{p,q}\) 可以 \(\mathcal{O}(k^2)\) 预处理。

\(f\) 数组可以滚掉一维,时间复杂度 \(\mathcal{O}(n^3 k^2)\)

D. 三染色

待补。

E. 广播

普及组 DP 题,设 \(f_{i,j}\) 表示匹配了 \(p_{i \sim n}\)\(q_{j \sim m}\) 的答案,容易写出转移,时间复杂度 \(\mathcal{O}(nm)\)

F. 最小环

注意到对于一个二度点,要么可以删掉,要么可以缩掉。这样处理之后每个节点的入度和出度的和至少为 \(3\),因此设最终得到的图的点数为 \(n'\),边数为 \(m'\),我们有 \(2m' ≥ 3n'\)

又由于图弱联通,我们每次做以上操作删除一个点时都至少删除了一条边。因此 \(m' −n' ≤ 1500\),得到 \(n' ≤ 3000,m' ≤ 4500\)。暴力枚举每个点跑最短路即可。

G. 【模板】线段树

首先发现 \(2\) 幂次很多的时候对答案没有贡献。我们考虑怎么记录下 \(2\)\(0 \sim 19\) 次幂对应的答案。

考虑类似生成函数那样,给每个偶数一个配重 \(x\),这样 \(x^k\) 就代表 \(2\) 的次幂至少为 \(k\)(因为这个偶数本来 \(2\) 的次幂可能不止是 \(1\),但是我们这样算显然不影响答案)。于是考虑维护 \(\prod(x + a_i) \bmod x^{20}\),打加法标记的时候直接令 \(x \gets x + \Delta\),二项式展开更新答案即可。

求乘积只需要返回常数项,时间复杂度 \(\mathcal{O}((n + q)\log n \cdot 20^2)\)

然后这个题卡常,你写正常的取模应该是过不去的,得用自然溢出取模再对 \(2^{20}\) 取模。

H. 哈密顿

首先把绝对值拆掉,改成这样:给每个 \(a_i,b_i\) 分配一个权重 \(1\)\(-1\),然后要求边 \((i,j)\)\(a_i\)\(b_j\) 权重必须一正一负,目标是让所有点带权的和最大。

考虑先不管哈密顿路这个限制,那直接让大的 \(n\) 个为正,小的 \(n\) 个为负就行了。但这样可能不存在哈密顿回路,我们需要仔细考虑这个哈密顿回路的条件。

以下我们用 \((-1,1)\) 表示给 \(a_i\) 权值 \(-1\),给 \(b_i\) 权值 \(1\)。手玩一下可以发现只有当同时存在 \((-1,1)\)\((1,-1)\),且不存在 \((1,1)\)\((-1,-1)\) 时不合法。

考虑通过调整贪心方案得到一组合法的解。一个直接的想法是交换第 \(n\) 大和第 \(n+1\) 大,但如果它们两个刚好来自同一个二元组那也不行。但你发现此时交换 \(n-1\)\(n+1\) 或交换 \(n\)\(n+2\) 就一定合法,所以我们直接比较所有四种方案的合法性并取符合条件的方案中的最优解即可。时间复杂度 \(\mathcal{O}(n \log n)\)

I. 勿蹖宠物

要求是回文串,考虑从两边往中间 DP。

然后我们考虑对每一个回文串钦定一个唯一的生成方式,并且每一步都能比较方便地处理回文匹配的条件。考虑这样:每次在长度较短的一边放一个字符串,如果两边长度相等就在左边放,这样是不重不漏的。

于是考虑设 \(f_{i,j,0/1}\) 表示当前串总长为 \(i\),左边/右边较长并且匹配到位置 \(j\),状态数是 \(\mathcal{O}(L \cdot \sum|s_i|)\) 的。转移枚举另一边放哪个串,需要满足能够匹配上,直接暴力预处理是 \(\mathcal{O}((\sum|s_i|)^2)\) 的。

最后若 \(j\) 对应的后缀是回文串就把 \(f_{L,j,0/1}\) 算进答案,总时间复杂度 \(\mathcal{O}(nL \cdot \sum|s_i| + (\sum|s_i|)^2)\)

以上做法纯口胡,不保证正确性。 但是感觉挺对的。

J. 图

容易证明或者直接猜到对于一条边 \((x, y)\),如果其是某两个点最短路的必经边,那么其一定是 \(x, y\) 之间最短路的必经边。

用 Floyd 预处理出全源最短路,然后暴力判定即可。时间复杂度 \(\mathcal{O}(n^3)\)

K. 报数 IV

显然最多迭代 \(4\) 次之后就会变成一位数,之后都不变。所以 \(k\) 其实最多是 \(4\)。可以把作用 \(k\)\(f\) 的过程拆成两部分:

  • 先作用一次 \(f\),得到一个不超过 \(9000\) 的数。
  • 再作用 \(k−1\)\(f\) 得到 \(m\)

第一个部分可以对每个 \(1 \le x \le 9000\) 数位 DP 出 \(1 \sim n\) 内有多少个数和为 \(x\),第二部分暴力判断即可。时间复杂度 \(\mathcal{O}(9^2 \cdot n^2)\)