代码源挑战赛 Round 55 题解 - 代码源竞赛平台

T1

100%

ay=c−bay = c - b y=c−bay = \frac{c - b}{a}

题目要求输出不大于 yy 的最大整数 y′y'。由于题目保证了 b≤cb \le c 且 a≥1a \ge 1,因此 c−b≥0c - b \ge 0。对于非负数,不大于它的最大整数就是它的向下取整值。因此直接输出 (c - b) / a 即可。

时间复杂度 O(1)O(1)。

T2

100%

每件礼物的实际贡献(心意值)是其基础价值与惊喜度的乘积,即 Vi×PiV_i \times P_i。为了用最少数量的礼物达到或超过目标心意值 XX,我们显然应该优先选择贡献最大的礼物。

故只需要将礼物按照心意值进行排序,之后一个一个取,直到对应的心意值 >X> X (注意不是 ≥X\ge X) 即可。

如果都取完了还没有满足条件,输出 -1。

时间复杂度 O(nlog⁡n)O(n \log n)。

T3

100%

根据题意,一个数字 kk 是“好的”,当且仅当它的所有质因数都完全包含在给定的质数序列 aa 中。由于题目保证了给定的序列 aa 中的元素全是质数,我们可以直接利用试除法来验证。

对于每一次询问的数字 kk:

  1. 我们遍历给定的质数序列 aa 中的每一个元素 aia_i。
  2. 如果当前的 kk 能够被 aia_i 整除,我们就通过不断除 aia_i 直到不能整除为止,通过这种方式将 kk 中的 aia_i 因子剥离出去。
  3. 当遍历完整个序列 aa 后,如果 kk 最后变成了 11,说明 kk 的所有质因数都在序列 aa 中,那么它就是一个“好的”数字,输出 YES;如果 k>1k > 1,说明 kk 还含有序列 aa 之外的质因数,因此输出 NO。

时间复杂度 O(nqlog⁡k)O(n q \log k)。

T4

100%

这个题主要的难点在于如何维护一个支持“尾部追加”和“局部连续删除”且删除后能维持先后顺序的数据结构。我们可以利用 set 来完成这一模拟过程。

由于每次放置新牌时,都是将其放在桌面所有牌的最右侧,这意味着:牌在桌面上的相对左右顺序,与它们被抽出来的回合序号(即初始序号 ii)的大小顺序是完全一致的。因此,我们可以用一个 set 来按顺序维护当前桌面上所有牌的初始序号。

同时,我们维护一个数组 pos[x]pos[x],用于记录数字为 xx 的牌当前在桌面上的初始序号。如果 pos[x]==0pos[x] == 0,则说明当前桌面上没有数字为 xx 的牌。

当游戏进行到第 ii 回合,抽出数字为 aia_i 的牌时,按照以下逻辑处理:

  1. 放置:如果 pos[ai]==0pos[a_i] == 0,说明桌面上不存在相同的牌。我们将它的初始序号 ii 记录下来:pos[ai]=ipos[a_i] = i,并将其插入到 set 中。
  2. 消除:如果 pos[ai]≠0pos[a_i] \neq 0,说明桌面上已经有这张牌,触发消除。此时手里这张牌直接丢弃,当前回合 ii 作为消除回合。我们需要在 set 中找到那张触发消除的牌的迭代器位置(利用 lower_bound)。 从这个迭代器开始,向后连续遍历最多 kk 张牌(需注意迭代器不能越界)。对于被消除的每一张牌,我们将它的被消除回合记录为当前回合,将其在桌面上的标记清空(修改 pospos),然后将其从 set 中删除。

时间复杂度为 O(nlog⁡n)O(n \log n)。当然本题用双向链表也是可以解决这个问题,具体维护方式和上面类似,这里不再赘述。

T5

100%

首先分析交互性质。当询问“xx 评价 yy”时,交互器的返回值存在以下真值表:

  • 精明人 评价 精明人 →1\rightarrow 1
  • 精明人 评价 糊涂人 →0\rightarrow 0
  • 糊涂人 评价 精明人 →0\rightarrow 0 (实际是 11,由于说谎变成 00)
  • 糊涂人 评价 糊涂人 →1\rightarrow 1 (实际是 00,由于说谎变成 11)

可以发现一个规律:如果 xx 和 yy 属于同一类人(同为精明人或同为糊涂人),一定会返回 1;如果属于不同类,一定会返回 0。

这意味着单次询问就能完美验证两人是否属于同一阵营。

我们可以固定向第 11 个人询问剩下所有的 n−1n-1 个人。这样就将所有人分为了两个阵营:“与 1 同阵营”和“与 1 不同阵营”。题目保证精明人占多数(≥⌊n2⌋+1\ge \lfloor \frac{n}{2} \rfloor + 1),所以人数较多的那个阵营一定全体都是精明人,另一个阵营则是糊涂人。

至此,我们只用了 n−1n-1 次询问就查清了所有人的真实身份。设初始糊涂人的总数为 CC。 题目要求从中挑选恰好 kk 个人进行反转。假设我们挑选了 ii 个糊涂人(使其变成精明人)和 k−ik-i 个精明人(使其变成糊涂人)。 翻转后,糊涂人的总数为:C−i+(k−i)=C+k−2iC - i + (k - i) = C + k - 2i。此时的痛苦度为 2C+k−2i2^{C + k - 2i}。

遍历所有合法的 ii(即 0≤i≤min⁡(C,k)0 \le i \le \min(C, k) 且 k−i≤n−Ck-i \le n-C),计算对应的方案数:

(Ci)×(n−Ck−i)\binom{C}{i} \times \binom{n - C}{k - i}

将方案数 ×\times 对应的痛苦度累加即可。

时间复杂度 O(n)O(n)。

# T6

100%

我们将每个节点的权值 aia_i 按二进制位独立处理,对于第 bb 位(0≤b<300 \le b < 30),问题转化为节点权值仅为 00 或 11 的树上组合求和。

对于三元组 (i,j,k)(i, j, k) 的最近公共祖先,设其为节点 uu。此时 w=parent(u)w = \text{parent}(u)。 一个三元组的 LCA 为 uu,当且仅当这三个节点都在 uu 的子树内,且这三个节点不全在 uu 的同一个子节点的子树内。

考虑容斥。设 T(u,c)T(u, c) 表示在节点 uu 的子树中,选取三个不同节点且这三个节点的权值异或和为 cc(c∈{0,1}c \in \{0, 1\})的方案数。 设 uu 的子树中权值为 00 的节点数为 C0C_0,权值为 11 的节点数为 C1C_1。

  • 异或和为 11 的方案(选择三个 11,或一个 11 和两个 00):$$T(u, 1) = \binom{C_1}{3} + C_1 \times \binom{C_0}{2}$$
  • 异或和为 00 的方案(选择三个 00,或一个 00 和两个 11):$$T(u, 0) = \binom{C_0}{3} + C_0 \times \binom{C_1}{2}$$

设 LCA 严格等于 uu 且子节点异或和为 cc 的合法三元组数量为 H(u,c)H(u, c),可以用容斥求得:

$$H(u, c) = T(u, c) - \sum_{v \in \text{children}(u)} T(v, c)$$

最后根据到外部祖先父亲节点 ww 的权值 vwv_w,只有当 c⊕vw=1c \oplus v_w = 1 时,这些三元组才会对当前第 bb 位的总答案有贡献。直接累加即可。

时间复杂度 O(nlog⁡V)O(n \log V)。

T7

100%

观察 O(nk)O(nk) 的 DP 状态转移:

  • 如果第 ii 题不是数数题(即发生了清零):当前方案对接下来的连续计数清零。dp[i][0]=∑j=0kdp[i−1][j]dp[i][0] = \sum_{j=0}^k dp[i-1][j]
  • 如果第 ii 题是数数题:将延续之前的序列长度。$$dp[i][j] = dp[i-1][j-1] \times a_{i, j} \quad (1 \le j \le k)$$

我们可以将状态定义为一个 1×(k+1)1 \times (k+1) 的行向量 Si=[dp[i][0],dp[i][1],…,dp[i][k]]S_i = [dp[i][0], dp[i][1], \dots, dp[i][k]]。 状态的转移可以用矩阵乘法表示:Si=Si−1×MiS_i = S_{i-1} \times M_i。 其中转移矩阵 MiM_i 是一个 (k+1)×(k+1)(k+1) \times (k+1) 的矩阵。具体如下:

  • 第 00 列的元素全为 11(对应转移到 dp[i][0]dp[i][0] 的求和,矩阵下标从 00 开始)。
  • 对于第 jj 列(1≤j≤k1 \le j \le k),只有第 j−1j-1 行的元素值为 ai,ja_{i,j},其余全为 00。

以 k=3k = 3 为例,状态向量有 44 列,对应的转移矩阵 MiM_i 如下:

$$M_i = \begin{bmatrix} 1 & a_{i,1} & 0 & 0 \\ 1 & 0 & a_{i,2} & 0 \\ 1 & 0 & 0 & a_{i,3} \\ 1 & 0 & 0 & 0 \end{bmatrix}$$

以此类推,最终答案的向量 $S_n = S_0 \times M_1 \times M_2 \times \dots \times M_n$。初始状态 S0=[1,0,…,0]S_0 = [1, 0, \dots, 0]。最终的总不满意度为 SnS_n 向量所有元素的和。

当发生修改操作时,我们仅修改了某一个位置 ii 对应的矩阵 MiM_i 中的单个元素。故我们可以利用线段树来维护矩阵的连乘积。最后计算 SnS_n 的和即可。

总时间复杂度为 O(n⋅k3+qlog⁡n⋅k3)O(n \cdot k^3 + q \log n \cdot k^3)。