- 代码源挑战赛 Round 40
代码源挑战赛 Round 40 题解
- @ 2026-6-13 17:24:24
A
题目要求判断给定的小时数 之后,时间是否处于 到 之间。
已知起始时间是 。经过 小时后,当前时刻的小时数为 。
只需要判断 是否成立即可。
- 如果成立,输出
I love Shawarma。 - 否则,输出
Shawarma is the best food。
时间复杂度 。
B
我们需要统计有多少个 满足存在区间 使得 。
记 。如果 ,显然不存在这样的区间(因为 均为正整数),可以直接忽略。
对于 的情况,我们需要快速判断数组中是否存在和为 的子数组。
注意到数据范围 ,我们可以使用 的时间预处理出所有可能的区间和。
总时间复杂度 ,空间复杂度 。
C
由于每一列的掉落是相互独立的,我们可以分别处理每一列。
对于每一列,箱子掉落的规则如下:
- 箱子会掉落到其下方最近的障碍物(
-)或堆叠的箱子/废墟之上。 - 我们可以从下往上(行号 到 )遍历每一列,维护一个变量 ,表示当前物体掉落后的预期放置行号。一开始 。
如果从下往上遍历时(假设此时遍历到第 个),会有下面几种情况:
- 遇到了
-,说明下一个物体只能落到这个平台上方,将 设置为 。 - 遇到了箱子,我们可以先计算掉落距离 ,然后根据题目要求判断其是否变成
*,接着我们把 修改为 。 - 遇到了
.,直接跳过。
时间复杂度为 。
D
假设 apiadu 解决 个题目,那么 jiangly 就要解决 个题目。
此时,疲劳值产生的时间是固定的,为:
现在的目标是让 $\sum_{i \in S_{\text{apiadu}}} a_i + \sum_{j \in S_{\text{jiangly}}} b_j$ 最小。(其中 为 apiadu 选择的题目。 为 jiangly 选择的题目。
将式子变形一下:
$$\begin{aligned} \sum_{i \in S_{\text{apiadu}}} a_i + \sum_{j \in S_{\text{jiangly}}} b_j & = \sum_{i \in S_{api}} a_i + (\sum_{\text{all}} b - \sum_{i \in S_{\text{apiadu}}} b_i) \\ &= \sum_{\text{all}} b + \sum_{i \in S_{\text{apiadu}}} (a_i - b_i) \end{aligned} $$其中 是常数。为了使总时间最小,我们需要在确定了 的情况下,选择 个题目进入集合 ,使得这 个题目的 的和最小。
故只需要选择 的 个题目给 apiadu 做就能让时间最小。
利用排序和前缀和可以 算出 apiadu 解决 个题的最小时间。枚举 即可。
时间复杂度为 。
E
先将 内的点按照 的值从小到大排序,考虑枚举排序后 中最编号最大的不在极大匹配中的编号,不妨设为 。
此时我们把点分成 类:
- 集合中 ,称为集合 。
- 集合中 ,称为集合 。
- 集合中 ,称为集合 。
- 集合中 ,称为集合 。
可以发现,集合 和集合 内的所有点在匹配上。(若集合 内存在没有被匹配的点,那么可以让 和这个点进行匹配,与题目假设不符;若集合 内存在没有被匹配的点,那么 就不是编号最大的不在极大匹配中的点。)
那么此时匹配内的边会是在下面几种情况:
- 集合 集合
- 集合 集合
- 集合 集合
对于第一种情况,我们考虑计算其方案数,考虑动态规划。 设 表示考虑 中排序后的前 个点(即 ),在 中恰好匹配了 个点的方案数。 转移方程为:
$$f_{i,j} = f_{i-1, j} + f_{i-1, j-1} \times \max(0, a_i - (j-1)) $$含义是: 要么不匹配(),要么匹配(从 转移)。如果匹配, 可以连接 范围内的任意点,但其中 个点已经被前面的 点占用了,所以有 种选择。
对于固定的 ,我们可以枚举 集合 与集合 之间的连边数量,设为 。 这部分的方案数即为 。
接下来处理剩余的情况:
-
填补集合 的剩余空位(处理情况 ): 集合 ()的总大小为 。既然集合 占用了 个位置,那么集合 中还剩下 个空位。 根据极大匹配的定义(以及 是最大未匹配点的假设),这 个空位必须被集合 中的点完全覆盖。
-
集合 的分配(处理情况 ): 集合 共有 个点。 其中,必须有 个点用来填补集合 的空位。 那么,集合 4 中剩余的点数为:
这 个点必须与 集合 中的点进行匹配。
-
计算总方案数: 由于集合 中的点满足 ,所以它们都可以填到集合 的空位上。 因此,计算步骤如下:
-
从集合 中选出 个点与集合 2 匹配。考虑用动态规划计算这一步。设 表示从 中选 个点匹配到 的方案数。
-
集合 中剩下的 个点,用来填充集合 的 个特定空位。由于点是不同的,空位也是不同的,这部分的方案数是全排列 。
故对于固定的 ,其对答案的贡献为:
$$\sum_{x} \left( f_{k-1, x} \times g[k] [(n-k) - (a_k - x)] \times (a_k - x)! \right) $$如何计算 ?考虑通过 转移到 。
可以发现,当 减少 时,集合 会新增 个点,且这些点都可以被集合 内的点连接。
我们可以把这 个空位一个一个加入,假设我们要加入一个新的点,设 为更新前的状态, 为更新后的状态,那么会有以下两种情况:
- 这个点没有被使用,此时贡献为 。
- 这个点被使用,此时贡献为 ,其中 表示集合 的大小。
由于新增了 个位置,我们只需要将上述过程重复 次即可。
最后加上所有 点都匹配(完美匹配)的情况,即 。
时间复杂度为 。
F
不妨设以 为根,对于某个节点 ,先考虑如何计算以 为起点的子树内所有路径权值之和。
定义 为 的路径上所有 sqr k 操作参数 的和。
根据题目定义, 的计算过程为:初始值 ,依次经过路径操作。
若路径上某条边为 * C,且该边之后(在通往 的方向上)累积经过了 次平方操作,则因子 在最终结果中会变为 。
由于指数 可能很大,根据费马小定理和扩展欧拉定理,我们有如下性质:
- 在模 下,底数的指数是模 的。
- 具有长度为 的前缀和长度为 的循环。
- 故总共只有 种本质不同的指数状态。我们将 映射到 的范围内,记为 。
所以我们按照这个指数状态对路径进行分类。
故设 表示 的子树中,所有满足 的节点 的路径值之和,即:
$$f[u][i] = \left( \sum_{v \in \text{subtree}(u), \ \text{Map}(S(u,v))=i} d(u,v) \right) \bmod P $$此时考虑转移,当合并子节点 到 ,且边 的值为 时:
-
假设边为
sqr k: 从 出发的第一步是对初始值 进行平方,,故数值不变。 但是对于子树中的任意节点 ,有 。 这意味着原本属于状态 的路径,现在的状态变为 。 故转移方程为: -
假设边为
$$f[u][i] \leftarrow f[u][i] + f[v][i] \times k^{2^i} $$* k: 从 出发的第一步是将初始值 乘以 ,变为 。 此后从 继续走到子树节点 ,这个因子 将会被后续的sqr操作平方 次。 即新的路径值为 。 此时路径的 值没有变化,。 故对于状态 (即 ),所有路径的值都要乘以 。 转移方程为:
此时 的答案为 。
其他位置的答案,可以通过换根 dp 来解决,这里不再赘述。
时间复杂度为 。