2024 EC Final 前集训记录

ECF23

Link

C. Equal Sums

记值域为 \(w\) 并认为 \(n,m\) 同阶,直接背包的话和的值域能够达到 \(O(nw)\),统计每个答案的复杂度也是 \(O(nw)\),于是总复杂度是 \(O(n^3w)\)

注意到最后需要维护的信息仅仅是 \(\sum x_i = \sum y_j \Leftrightarrow \sum x_i - \sum y_j = 0\),记这个差为 \(d\),我们实际上能够通过调整两侧加入的顺序来将 \(d\) 控制在 \([-w,w]\)

具体而言,考虑若有 \(\sum_{i=1}^a x_i - \sum_{j=1}^b y_j = 0\),可以按如下算法构造一条从 \((0,0)\)\((a,b)\) 的路径:

  1. 设变量 \(i=0,j=0\) 表示当前位置,\(d=0\) 表示两侧和之差。

  2. \(d \leq 0\),令 \(d \leftarrow d+x_{i+1}, i \leftarrow i+1\).

  3. \(d > 0\),令 \(d \leftarrow d-y_{j+1}, j \leftarrow j+1\).

  4. \(i=a, j=b\) 时停止。可以发现 \(i=a\)\(i\) 不会再增加,\(j=b\)\(j\) 不会再增加,故一定能够停止。

  5. 由此构造出三元组序列 \(P=\{i_t,j_t,d_t\}\).

可以发现一个合法的 \(P\) 一定对应唯一的 \((\{x_i\},\{y_i\})\),故其构成双射。

整个过程中 \(d\) 都被控制在 \([-w,w]\) 内,于是设 \(dp_{i,j,d}\) 表示上述算法进行到状态 \((i,j,d)\) 的方案数,用一点前缀和优化转移。时间复杂度 \(O(nmw)\).

I. Balance

考虑 \(x=\text{argmin}\{a_i\}, y=\text{argmax}\{a_i\}\),拉出 \(x \leadsto y\) 的任意一条路径 \((d_1=x,d_2,\cdots,d_k=y)\),然后:

\[\sum\limits_{(u,v) \in E} |a_u-a_v| \geq \sum\limits_{i=1}^{k-1} |a_i-a_{i+1}| \geq |a_x-a_y| = \max\{a_i\} - \min\{a_i\} \]

这跟题目给出的不等号方向相反,所以所有不等号都必须取等,也就是说:

  • 路径上点权递增,即 \(\forall t \in [1,k), a_{d_i} < a_{d_{t+1}}\).

  • 除了路径的其他边的两个端点权值必须相等,即 \(\forall (u,v) \notin E(\text{path}), a_u=a_v\).

  • 推论:任意一个点的点权必须在路径上出现过,即 \(\forall u \in V, \exist x \in V(\text{path}), a_u=a_x\).

于是将所有出现的点权排序并记 \(c_i\) 表示第 \(t\) 大点权有多少个点。枚举 \(x \leadsto y\) 的路径的 LCA,分别考虑 LCA 的前后路径。以前面的路径为例,记第 \(t\) 大点权深度最浅的点是 \(b_i\),那么必须有 \(siz_{b_i} = \sum_{j=1}^t c_j\)\(b_i \in subtree_{b_{t+1}}\).

注意到对于一个点 \(u\),满足 \(siz_u = \sum_{j=1}^t c_j\)\(t\) 至多只有一个,记为 \(f_u\)(若不存在则为 \(0\))。直接转移即:

\[f_u = [siz_u = \sum_{j=1}^t c_j] \cdot [\max\limits_{v \in subtree_u}\{f_v\} = t-1] \]

DP 完枚举 LCA 统计即可,一车细节。时间复杂度 \(O(n)\).

ECF22

Link

A. Coloring

称颜色为 \(1\) 的点为黑点,为 \(0\) 的点为白点。

首先连边 \((a_i,i)\),由于每个点入度均为 \(1\),图一定是外向基环树(只关心 \(s\) 所在的连通块,可能有自环)。

先只考虑环上,容易发现任意时刻环上黑点一定形成一个区间 \([l,r]\),并且它们可以不断向右移动。枚举最后 \(l,r\) 的值以及转了几圈,就可以确定每个点变化了多少次(以及最后的颜色)。

再考虑每棵子树,环上点颜色变化的次数决定了一条链上黑白交替的最大次数。设 \(f_{u,t},g_{u,t}\) 表示黑白交替了变化 \(t\) 轮且最后是黑点/白点的最大贡献,树上 DP 即可。

枚举 \(l,r\) 可以用前缀和优化,一百车细节。时间复杂度 \(O(n^2)\).

B. Binary String

这不是我出的题吗·

alt text

不过其实环上的问题不需要转换成序列做。找到上面提到的循环移位,然后按转化后的操作容易维护某时刻所有 \(R\) 的位置(虽然这题并不需要)。

这题里扫一遍求出 \(R\) 什么时候停止移动,然后跑 KMP 算出最小周期即可。复杂度 \(O(n)\).

ECF21

Link

C. String-dle Count

所有信息可以转化为四种限制:

  1. 位置 \(p\) 上必须填字母 \(c\)

  2. 位置 \(p\) 上不能填字母 \(c\)

  3. 字母 \(c\) 出现了恰好 \(t\) 次。

  4. 字母 \(c\) 出现了至少 \(t\) 次。

直接子集卷积是 \(O(|\Sigma| k^2 2^k)\),无法通过。

利用一些性质,记字母 \(c\) 出现次数的下限为 \(f_c\),那么必须有 \(\sum_c f_c \leq k\),否则必然无解。

一个神奇的 trick:记 \(dp_{i,state}\) 表示填前 \(i\) 个位置,状态为 \(state\) 的方案数。\(state\) 记录每种字符 \(c\) 填了超过 \(f_c\) 个 / 未超过 \(f_c\) 个且具体填了几个。

实现时可以新建一个序列,填入 \(f_c\) 个字符 \(c\),然后直接用二进制数状压 \(state\)。总时间复杂度 \(O(|\Sigma| k 2^k)\).

UCup2nd Hangzhou

Link

C. Yet Another Shortest Path Query

平面图 Trick 题。

平面图满足性质 \(m \leq 3n-6\),由抽屉原理可得至少有一个点度数不超过 \(5\)。于是不停地删去度数 \(\leq 5\) 的点,得到每个点被删去的时间戳 \(p_u\)

考虑将每条边 \((u,v)\) 看作两条有向边 \(u \to v\), \(v \to u\)

  • \(p_u > p_v\),记该边为 R 型边。每个 \(u\) 至多只有 \(5\) 条 R 型出边。

  • \(p_v < p_u\),记该边为 L 型边。每个 \(v\) 至多只有 \(5\) 条 L 型入边。

接下来考虑可能的路径类型,先考虑 \(len=3\),记 X 表示 L 或 R:

  • RXX:枚举 \(s\) 的 R 型出边,转化为 \(5\)\(len=2\) 的子问题。

  • XXL:枚举 \(t\) 的 L 型入边,转化为 \(5\)\(len=2\) 的子问题。

  • LRR:按 \(s\) 离线,枚举 \(s\) 的所有 L 型出边再枚举两层 R 型出边,\(25\) 次枚举.

  • LLR:按 \(t\) 离线,枚举 \(t\) 的所有 R 型入边再枚举两层 L 型入边,\(25\) 次枚举.

LRRLLR 的复杂度大约为 \(O(50m)\),同时产生了至多 \(10q\)\(len=2\) 子问题。

对于 \(len=2\),同样:

  • RX:枚举 \(s\) 的 R 型出边,转化为 \(5\)\(len=1\) 的子问题。

  • XL:枚举 \(t\) 的 L 型入边,转化为 \(5\)\(len=1\) 的子问题。

  • LR:按 \(s\) 离线,枚举 \(s\) 的所有 L 型出边再枚举一层 R 型出边,\(5\) 次枚举.

LR 的复杂度大约为 \(O(10q+m) \cdot 5 = O(50q+5m)\),同时产生了至多 \(100q\)\(len=1\) 子问题。

对于 \(len=1\),直接枚举 \(s\) 的 R 型出边和 \(t\) 的 L 型入边。这里的复杂度大约为 \(O(1000q)\).

于是总复杂度上界大概是 \(O(1000q+50m)\)。注意实现时 \(len=1\) 的子问题可以直接计算,不需要存下来。

I. Dreamy Putata

列出方程,发现每一层可以由上面两层递推而来。假设不考虑 \((tx,ty)\) 处方程的特殊性,直接以前两层 \(2m\) 个点为主元,用线段树维护矩阵乘法计算转移矩阵,最后再以第一行和最后一行导出的方程组高斯消元即可。

但是 \((tx,ty)\) 处方程不一样,为 \(f_{tx,ty}=0\),所以 \(f_{tx+1,ty}\) 实际上是没有办法用前两层的主元推出的。所以设 \(f_{tx+1,ty}\) 为一个新的主元,同时由于 \(f_{tx+1,ty}\) 可以用前两层主元表示,新增了一个方程组,故最后得到的方程组数量和主元数量还是一致的。

注意上述做法有一车特殊情况,比如 \(tx=0\)(新主元和原主元会重复),\(tx=n-1\)(没有新主元,第一行少导出一个方程组)。以及由于 \(tx\) 前后转移不一样,需要分段算;以及方程里的常数项导致需要新开一个矩阵乘法线段树。

总时间复杂度 \(O(q (2m)^3 \log n)\).

CCPC Final 2023

Link

B. Periodic Sequence

首先找上界。有一个显然的结论:对于任意一个可能出现的字符串 \(S_i\),一定存在 \(k \leq |S_1|\) 使得 \(S_i = S_1[1:k] + S_1[1:i_1] + \cdots + S_1[1:i_t]\),其中 \(1 \leq i_1, i_2, \cdots, i_t \leq k\)。容易归纳证明。

所以上界显然就是令 \(S_1 = \text{'a'}+\text{'b'} \times (n-1)\) 时,所有这样的序列的个数,下面证明存在一个字符串序列能将它们全部串起来。

\(n\)\(1\) 枚举 \(k\)。对于某个 \(k\),把所有字符串连成一棵树,\(S_i = S_1[1:k] + S_1[1:i_1] + \cdots + S_1[1:i_t]\) 即看作依次走边 \(i_1,i_2,\cdots,i_t\) 到达的点。显然所有深度不超过 \(l-k\) 的点与所有可能的字符串一一对应。

那么假设现在字符串序列的末尾对应的节点是 \(u\),添加一个新的串在树上对应:

  1. 对于所有 \(u\) 的儿子 \(v\),可以走到 \(v\)(对应新增一个前缀)。

  2. 对于所有 \(u\) 的祖先 \(x\),若 \(y\)\(x\) 的某个更小的兄弟,则可以走到 \(x\)\(y\)(对应删去一个后缀)。

  3. 可能可以走到比儿子更深的节点,但此证明中不考虑。

按深度归纳证明如果初始时在根节点,那么可以遍历树上所有节点(并在某个节点停止)。假设根节点的儿子(按边权从小到大)依次为 \(s_1,s_2,\cdots,s_k\),且 \(s_i\) 子树下按归纳假设构造的路径停止在 \(t_i\) 节点,那么直接按照以下方式构造:

\[\text{root} \to s_k \leadsto t_k \to s_{l-1} \leadsto t_{l-1} \to \cdots \to s_1 \leadsto t_1 \]

最后,对于不同的 \(k\),也可以类似上面的路径从大到小把根串起来。于是证明了存在一个字符串序列能将它们全部串起来,即上限能达到。


接下来考虑计数,枚举 \(k\),则有:

\[\begin{aligned} f(l) &= \sum\limits_{k=1}^l [x^l] \dfrac{1}{1-x} \cdot x^k \cdot \text{SEQ}[x+x^2+\cdots+x^k] \\ & = [x^l] \sum\limits_{k=1}^l \dfrac{x^k}{1-2x+x^{k+1}} \\ \end{aligned} \]

一种暴力做法是对于某个 \(k\),转成线性递推,可以 \(O(n)\) 算出所有系数。

另一种做法是暴力拆开:

\[\begin{aligned} [x^l] \dfrac{x^k}{1-2x+x^{k+1}} &= [x^{l-k}] \sum\limits_{t \geq 0} x^t (2-x^k)^t \\ &= \sum\limits_{t \geq 0} [x^{l-k-t}] (2-x^k)^t \\ (\text{let } t = l-kr,) &= \sum\limits_{r \geq 0} [x^{kr-k}] (2-x^k)^{l-kr} \\ &= \sum\limits_{r \geq 0} \dbinom{l-kr}{r-1} (-1)^{r-1} 2^{l-(k+1)r+1} \\ \end{aligned} \]

注意这里出现了 \(kr\),于是考虑根号分治。对于 \(k < B\),用前面提到的暴力做法;对于 \(k \geq B\),一定有 \(r \leq \lfloor n/B \rfloor \triangleq B_0\),然后枚举 \(r\)

\[\begin{aligned} f_0(l) &= \sum\limits_{k=B}^l \sum\limits_{r \geq 0} \dbinom{l-kr}{r-1} (-1)^{r-1} 2^{l-(k+1)r+1} \\ &= \sum\limits_{r=0}^{B_0} (-1)^{r-1} 2^{l-r+1} \sum\limits_{k=B}^l \dbinom{l-kr}{r-1} 2^{-kr} \\ \end{aligned} \]

\[g_{r,l} \triangleq \sum\limits_{k \geq B} \dbinom{l-kr}{r-1} 2^{-kr} \\ \begin{aligned} g_{r,l+r} &= \sum\limits_{k \geq B} \dbinom{l+r-kr}{r-1} 2^{-kr} \\ &= \sum\limits_{k \geq B-1} \dbinom{l-kr}{r-1} 2^{-(k+1)r} \\ &= 2^{-r} \Big[ g_{r,l} + 2^{-r(B-1)} \dbinom{l-r(B-1)}{r-1} \Big] \\ \end{aligned} \]

\(B = O(\sqrt n)\),时间复杂度 \(O(n \sqrt n)\)

K. Sticks

场上推出来结论,调了半天发现好像假了,换了个容斥做法赛后又调了一晚上。结果在写这篇题解的时候突然发现场上做法没假,改了三行过了...

设左侧第 \(i\) 行的棍子长度为 \(x_i\),上方第 \(j\) 列的棍子长度为 \(y_j\)

定义:对于一种摆放方式,若 \(\forall i \in [1,n], y_{x_i+1} \neq i\),称其该摆放方式合法,即不存在以下形状:

...|
...|
-->∨

Lemma 1. 任意一个可能达到的矩阵 \(A\) 都存在至少一种合法摆放方式。

Proof 1. 对于 \(A\) 的任意一种摆放方式,找到最小的 \(x_i\) 使得 \(y_{x_i+1} = i\) 并令 \(y_{x_i+1} \leftarrow y_{x_i+1}-1, x_i \leftarrow x_i+1\)。调整后冲突的最小 \(x_i\) 至少增加 \(1\),故有限次调整后能找到一种合法摆放方式。

Lemma 2. 任意零一矩阵 \(A\) 至多只有一种合法摆放方式。

Proof 2. 枚举 \(k=n,n-1,\cdots,1\),不断执行以下流程:

  • 求出 \(t \in [0,k]\) 满足 \(A_{k,1}=A_{k,2}=\cdots=A_{k,t}=1, A_{k,t+1}=0\). 那么必然有 \(y_k=t\),且若 \(s>t, A_{k,s}=1\) 则有 \(x_s = k\) 并删去第 \(s\) 行(若不全为 \(1\) 则终止)。

该流程要么提前终止,要么给出唯一的合法摆放方式并且没有其他可能。

Collary. 所有可能达到的矩阵 \(A\) 与合法摆放方式构成双射。


于是现在问题变为了计数满足 \(\forall i \in [1,n], y_{x_i+1} \neq i\)\((\{x_i\},\{y_i\})\) 序列数量。

\(dp_{i,j}\) 表示考虑前 \(i\) 列且 \(\max_{t=1}^i \{y_t\}=j\)。转移考虑分成

  1. \(y_{i+1} \leq j\),则转移为 \(dp_{i,j} \to dp_{i+1,j}\),系数直接乘上方案数即可。

  2. \(y_{i+1} > j\),则转移为 \(dp_{i,j} \to dp_{i+1,k} (k>j)\),相当于要求 \(x_{j+1}, x_{j+2}, \cdots, x_{k-1} \leq i\)\(x_k < i\),分步转移即可。

总时间复杂度 \(O(n^2)\)

M. Bot Friends

首先注意到没有 bot 能到达 \(0\)\(n+2\) 位置(容易反证),也就是说 bot 只能到达 \(n+1\) 个坑,那么必然恰有一个坑最后是空的。

同理,只考虑区间 \([l,r]\) 内的 bot,如果最后空出来的坑在最左边,称这个区间为 R 型块;如果最后空出来的坑在最右边,称这个区间为 L 型块。那么考虑整个过程,依次考虑每一步:

  1. 每一步中,如果移动的机器人向右并且它右边紧挨着一个 L 型块,那么它与 L 型块合并成一个新的 R 型块并重复这个过程;否则它自己成为一个新的 R 型块。

  2. 如果移动的机器人向左并且它左边紧挨着一个 R 型块,那么它与 R 型块合并成一个新的 L 型块并重复这个过程;否则它自己成为一个新的 L 型块。

所以整个过程始终只有未操作的 bot,L 型块与 R 型块。那么最后的局面一定是左边若干 L 型块 + 右边若干 R 型块。问题就是最小化未能合并(自己成为一个新块)的 bot 数量。

同时注意到如果在合并过程中建边,会形成一棵类似表达式树的结构,如:

  • R 型块 = '>' + (L型块)*;或者 R 型块 = '>'(花费 \(1\) 代价)

  • L 型块 = (R型块)* + '<';或者 L 型块 = '<'(花费 \(1\) 代价)

分析到这里已经可以区间 DP,记 \(f_{l,r},g_{l,r}\) 分别表示 \([l,r]\) 为 L 型块与 R 型块时的最小代价。时间复杂度 \(O(n^3)\)

既然是表达式树,就可能可以通过从左到右扫描并维护栈来描述它。先只考虑最后全为 L 型块的情况(即最后状态的一个前缀),可以将 > 类似看作左括号并将 < 类似看作右括号,有如下规则:

  • 遇到 >:在栈上插入一个 >;如果下一个 bot 立刻将它删去,则会产生 \(1\) 的代价(对应 R 型块 = '>')。

  • 遇到 <:弹栈一次;或者花费 \(1\) 代价不删除(对应 L 型块 = '<')。

于是直接记 \(dp_{i,j,0/1}\) 表示处理到第 \(i\) 个 bot,栈内有 \(j\)>,第 \(i\) 个 bot 是否是 > 的最小代价,容易转移。

最后对左右各做一次,枚举最后状态的坑位置合并即可。时间复杂度 \(O(n^2)\)

ECF19

Link

B. Black and White

经过多番尝试之后,一步一步考虑基本上不可能很好地挖掘性质。一个好的想法是两步两步考虑。

首先对于考虑 \(2 \nmid n+m\) 的情况,可以枚举第一步来转化为 \(2 \mid n+m\)

那么现在 \(n+m\) 步被划分为了 \((n+m)/2\) 组。记向上走为 A,向右走为 B,考虑两种贡献计算方式:

  1. 向右走时不计算贡献,向上走时计算左侧的贡献。容易发现 AA 和 BB 始终不产生贡献,而剩下两种:
(x mod 2, y mod 2) BA AB
\((0,0)\) \(1\) \(0\)
\((1,1)\) \(0\) \(-1\)
  1. 向上走时不计算贡献,向右走时计算上方的贡献。这时贡献的计算与 \(n\) 奇偶性有关:
(x mod 2, y mod 2) BA(2 | n) AB (2 | n) BA (2 ∤ n) AB (2 ∤ n)
\((0,0)\) \(0\) \(-1\) \(1\) \(0\)
\((1,1)\) \(1\) \(0\) \(0\) \(-1\)

看起来没有规律很难处理,但是如果我们把两种计算方式加起来(算两次),就会发生神奇的事情:

(x mod 2, y mod 2) BA(2 | n) AB (2 | n) BA (2 ∤ n) AB (2 ∤ n)
\((0,0)\) \(1\) \(-1\) \(2\) \(0\)
\((1,1)\) \(1\) \(-1\) \(0\) \(-2\)
  • 先考虑 \(2 \mid n,m\),此时贡献已经跟位置没有关系了,直接枚举 BA 填了 \(t\) 个,AB 填了 \(t-k\) 个,可以算出 AA 和 BB 的数量,然后直接可重排:

\[Ans = \sum\limits_{t=\max\{0,2k\}}^{\min\{n,m\}/2+k} \dbinom{(n+m)/2}{t,t-2k,n/2-t+k,m/2-t+k} \]

  • 对于 \(2 \nmid n,m\),注意到如果给每个 \((0,0)\) 减一,给每个 \((1,1)\) 加一,就可以归到前一种情况。而 \((0,0)\) 一定比 \((1,1)\) 多一,因此先把 \(k\) 减一再照前一种情况做即可。

时间复杂度 \(O(T\min\{n,m\})\).

posted @ 2024-12-21 19:28  苹果蓝17  阅读(19)  评论(1编辑  收藏  举报