- 代码源挑战赛 Round 16
代码源挑战赛 Round 16 题解
- @ 2026-3-16 18:30:44
T1
100%
根据题目描述,及格、良好、优秀的成绩区间分别为 ,,。
要使总分最大,我们需要让每个科目的分数尽可能高。因此,假设所有及格的科目都是 分,良好的科目都是 分,优秀的科目都是 分。总分的最大值即为 。
同理,要使总分最小,我们需要让每个科目的分数尽可能低。假设所有及格的科目都是 分,良好的科目都是 分,优秀的科目都是 分。总分最小值即为 。
时间复杂度 。
T2
100%
设按 按钮的次数为 ,则按 按钮的次数为 。
我们需要在 的范围内找出一个整数 ,使得总得分满足 成立。
由于 ,我们可以直接使用一层循环,枚举 从 到 。对于每个枚举到的 ,如果上式等号成立,说明存在这种按键组合,输出 YES 即可。
如果在循环结束后依然没有找到任何满足条件的 ,说明无论如何组合也无法得到恰好 分,输出 NO。
单组数据时间复杂度 ,对于 组数据总时间复杂度为 。
T3
40%
根据题意,我们需要找出满足条件的三元组 。对于较小的数据范围,可以直接使用三重循环枚举 (其中 ),然后判断是否满足 。如果满足则将答案加一。
时间复杂度 。
100%
我们观察到题目中的条件 完全与 以及 无关。
不妨假设 ,则 且 。代入条件可得 ,化简即 。 综合可能的大小关系,该条件在所有情况下都等价于 。
由于条件是否成立只与 和 有关,因此只要固定了 和 且两者满足上述条件,所有处于 和 之间(即 )的 都是合法的。这样的 共有 个。
于是,我们只需两重循环枚举 和 (),如果满足 ,就将总方案数加上 。
另外,满足条件的三元组数量最大可能达到 ,所以累加答案的变量必须使用 long long 以避免溢出。
时间复杂度 。
T4
30%
当 时,所需要的最小初始能量非常小。可以直接从 递增枚举初始能量,并在内层循环中模拟依次闯关的过程。如果枚举到的能量能保证全流程不出现能量 的情况,则输出该能量并结束。
时间复杂度 。
100%
解法一:二分答案
假设面对第 个关卡时有 点能量,通关后能量变为 。 因为随着 的增加, 严格增加,所以 显然是关于 的单调递增函数。这说明如果初始能量 能够顺利通关,那么大于 的初始能量也一定能通关。既然具有单调性,我们可以采用二分搜索的方法求解最小初始能量。
二分的上限可以设为所有 的总和(最大可达到 级别)。每次二分出一个 后,通过 模拟判断是否会出现失败即可。
时间复杂度 。
解法二:倒推法
定义 为通过第 关所需要的最小能量。通关所有关卡后剩余能量至少为 ,因此初始有 。我们需要倒推求 。 假设已知通过后续关卡所需的最小能量为 。在面对第 个关卡时,我们具有的能量为 (必须满足 )。设消耗 后剩余的能量为 。 那么通过第 个关卡后的能量就变为了 ,要使后续关卡顺利通过,我们需要满足 。 考虑求出满足该式的最小的非负整数 :
- 如果 ,此时 ,方程化为 ,可得最小的 $y = \lceil E_{i+1} / 2 \rceil = \lfloor(E_{i+1} + 1) / 2\rfloor$;
- 如果 ,此时必有 ,方程化为 ,可得最小的 。
求出最小的 后,便能得到 。从 倒序递推到 ,便可一次性在线性时间求出 。
时间复杂度 。
T5
40%
当 时,可以直接使用三维动态规划 表示已经确定了前 个数字,且第 个数字为 ,前 个数字的总和为 的合法方案数。状态转移时枚举下一个数字即可。
时间复杂度约 。
100%
实际上本题是在求 的 分拆,具体可以参考 分拆数 这个链接。
可以使用动态规划。设 表示将整数 划分为 个正整数的方案数。
转移方程可以通过两种情况讨论:
- 划分中包含至少一个 :等价于将 划分为 个正整数(即 ,可以理解成所有满足 划分为 个整数的方案的末尾放了一个 )。
- 划分中所有数都大于 :我们可以将所有 个数都减去 ,对应的方案数为将 划分为 个正整数(即 ,可以理解成所有满足 划分为 个整数的方案中所有数字都加了 )。
故状态转移方程为:
边界状态为 。记得要对 取模。
在处理每个查询时,只需 输出 即可。时间复杂度 。
T6
10%
对于 ,题目中的前置知识点关系构成了一个小规模的有向树林。
我们可以通过递归或 next_permutation 暴力生成该依赖图的所有合法的拓扑排序方案。将这些序列生成完毕后按字典序排序,并直接查找有几个序列比给定的方案 字典序更小。
时间复杂度 。
100%
在 知识点学习2 中,已经学习过给定一个森林(树)求其拓扑排序的方案数。这里不再赘述。可以简单化简 [知识点学习2] 中的状态转移方程,可以得到:
$$dp[u] = \frac{(sz[u] - 1)!}{\prod_{i=1}^k (sz[v_i]!)} \times \prod_{i=1}^k dp[v_i] $$其中 指的是 的子节点。
现在回到原问题:求字典序小于 的拓扑排序方案数。
求字典序更小的排列的经典做法是:枚举序列在哪一位(设为第 位)“首次偏小”。
首先在 从小变大的过程中,我们维护一个集合 ,表示当前所有“前置知识点已经学习完毕,可以立刻学习”的知识点(即当前森林的所有树根)。同时我们记 表示按照前 个点填之后的可以立即学习的知识点集合。初始时, 包含所有 的节点。
假设前 位我们都紧跟着原排列 ,在第 位我们选择了一个不同的、且编号小于 的合法节点 (即 )。那么接下来还剩下 个位置需要排。
为了之后计算的方便,我们记 为:把当前集合 中的所有子树直接混合排列,总的组合方案:
$$base = \frac{(n - i + 1)!}{\prod_{r \in S_{i - 1}} (sz[r]!)} \times \prod_{r \in S_{i - 1}} dp[r] $$但是,因为我们强制选了 排在当前位,这相当于剥离了 作为树根的限制,同时多了 的子节点构成的树,即此时剩余未排节点构成的森林根节点集合恰好是 $(S_{i - 1} \setminus \{v\}) \cup \{v \text{的子节点} \}$。此时的方案为:
$$\begin{aligned} \frac{(n - i)!}{\prod_{r \in S_{i - 1} \cap r \not = v } sz[r]! \times {\prod_{c \in \text{children}(v) }sz[c]!} } \times \big( \prod_{r \in S_{i - 1} \cap r \not = v }dp[r] \times \prod_{c \in \text{children}(v) }dp[c] \big) \end{aligned} $$其中 表示 的子节点构成的集合。
考虑对上述式子进行化简:
$$\begin{aligned} & \frac{(n - i)!}{\prod_{r \in S_{i - 1} \cap r \not = v } sz[r]! \times {\prod_{c \in \text{children}(v) }sz[c]!} } \times \big( \prod_{r \in S_{i - 1} \cap r \not = v }dp[r] \times \prod_{c \in \text{children}(v) }dp[c] \big)\\ = & \big( \frac{(n - i)! }{\prod_{r \in S_{i - 1} \cap r \not = v } sz[r]! } \times \prod_{r \in S_{i - 1} \cap r \not = v }dp[r] \big) \times \big( \frac{1 }{\prod_{c \in \text{children}(v) }sz[c]!} \times \prod_{c \in \text{children}(v) }dp[c] \big) \\ = & \big( \frac{(n - i)! \times sz[v]! }{\prod_{r \in S_{i - 1}} sz[r]! } \times \prod_{r \in S_{i - 1} \cap r \not = v }dp[r] \big) \times \big( \frac{1 }{\prod_{c \in \text{children}(v) }sz[c]!} \times \prod_{c \in \text{children}(v) }dp[c] \big) \\ = & \big( \frac{(n - i)! }{\prod_{r \in S_{i - 1}} sz[r]! } \times \prod_{r \in S_{i - 1} \cap r \not = v }dp[r] \big) \times \big( \frac{sz[v]! }{\prod_{c \in \text{children}(v) }sz[c]!} \times \prod_{c \in \text{children}(v) }dp[c] \big) \\ = & \big( \frac{(n - i)! }{\prod_{r \in S_{i - 1}} sz[r]! } \times \prod_{r \in S_{i - 1} \cap r \not = v }dp[r] \big) \times \big( \frac{(sz[v] - 1)! }{\prod_{c \in \text{children}(v) }sz[c]!} \times \prod_{c \in \text{children}(v) }dp[c] \big) \times sz[v] \\ = & \big( \frac{(n - i)! }{\prod_{r \in S_{i - 1}} sz[r]! } \times \prod_{r \in S_{i - 1} \cap r \not = v }dp[r] \big) \times dp[v] \times sz[v] \\ = & \big( \frac{(n - i)! }{\prod_{r \in S_{i - 1}} sz[r]! } \times \prod_{r \in S_{i - 1} }dp[r] \big) \times sz[v] \\ = & (\frac{base}{n - i + 1}) \times sz[v] \end{aligned} $$也就是说,如果我们第 个位置选了 ,那么此时对答案的贡献便是 ,故如果是在第 个位置开始与 不同,它的方案数是:
$$\frac{base}{n - i + 1} \times (\sum_{v \in S_{i - 1} \cap v < A_i} sz[v]) $$可以发现, 这一步我们可以很方便的用树状数组或者线段树进行维护,只需要加入节点 时在树状数组对应位置加 ,移除时减 。而$\frac{base}{n - i + 1} = \big( \frac{(n - i)! }{\prod_{r \in S_{i - 1}} sz[r]! } \times \prod_{r \in S_{i - 1} }dp[r] \big)$ 可以在维护 的时候顺便计算出来。
时间复杂度为 。