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

T1

100%

直接根据题目要求进行判断和计算即可。

先判断外卖的菜品总价 SS 是否满足满 100100 元的条件:

  • 如果 S≥100S \ge 100,则享受立减 2020 元的优惠,实际菜品花费为 S−20S - 20 元。
  • 如果 S<100S < 100,则不享受优惠,实际菜品花费为 SS 元。

最后,不管是否享受过优惠,都需要加上固定 55 元的配送费。

输出最终求得的实际菜品花费与配送费的和即可。

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

T2

100%

我们可以直接通过循环模拟倒水的过程。

从 i=1i = 1 到 n−1n - 1 依次遍历每个杯子进行操作:

在第 ii 次操作中,第 i+1i+1 个杯子最多还能装的水量,等于其最大容量减去当前水量,即剩余容量 rem=bi+1−ai+1rem = b_{i+1} - a_{i+1}。

第 ii 个杯子会尽可能多地倒水,所以实际倒给第 i+1i+1 个杯子的水量为 W=min⁡(ai,rem)W = \min(a_i, rem)。

倒水完成后,更新两个杯子的水量:第 ii 个杯子的水量变为 ai−Wa_i - W,第 i+1i+1 个杯子的水量变为 ai+1+Wa_{i+1} + W。 当 n−1n - 1 次操作全部执行完毕后,按顺序输出数组 aa 的每个元素。

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

T3

100%

题目保证根据给出的信息,排列方式只有一种,这意味着所有人构成了一条完整的接力链。我们可以顺着接力棒传递的顺序,从前往后依次计算出每名选手的起跑时间。

已知 aia_i 是第 ii 个人前一棒的选手编号,这就说明第 ii 个人是 aia_i 的下一棒。因此,我们可以建立一个数组 nxtnxt,令 nxt[ai]=inxt[a_i] = i,用来记录每个人要把接力棒传给谁。

同时,找出满足 ai=0a_i = 0 的选手,这名选手就是第一棒起跑的选手,将其记为起点。

接下来,从起点开始,顺着 nxtnxt 数组依次向后遍历,设 nownow 为当前在跑步的选手(初始为 pp),timtim 表示当前已经经过的时间:

  1. 将当前选手 nownow 的起跑时间记录为 timtim。
  2. 当前选手跑完后,时间会流逝 tnowt_{now},因此更新时刻 tim:=tim+tnowtim := tim + t_{now}。
  3. 下一位选手起跑,即更新 now=nxt[now]now = nxt[now]。

由于总共有 nn 个人,只需按上述逻辑循环推导 nn 次,即可求出所有人的起跑时间,最后按编号顺序输出即可。

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

T4

100%

首先分析题目中的两种操作会对答案产生什么影响。

对于选定的前缀 ii,如果我们给 a1,a2,…,aia_1, a_2, \dots, a_i 全部加上 11,那么两数组的积 ∑j=1najbj\sum_{j=1}^n a_j b_j 实际上会增加 ∑j=1ibj\sum_{j=1}^i b_j。

同理,如果我们给 a1,a2,…,aia_1, a_2, \dots, a_i 全部减去 11,总的积会减少 ∑j=1ibj\sum_{j=1}^i b_j。

记 Si=∑j=1ibjS_i = \sum_{j=1}^i b_j 为数组 bb 的前缀和。

那么对于前缀 ii 实施一次最佳操作(如果 Si>0S_i > 0 我们选择加法,如果 Si<0S_i < 0 我们选择减法),我们总是能让总的积增加 ∣Si∣|S_i|。

注意到对于任意一个前缀 ii,它能带来的单次最大收益就是固定的 ∣Si∣|S_i|,而且不同前缀的操作是完全独立、互不干扰的。为了让两数组最终的积最大化,我们只需要贪心地执行操作:优先选择能够带来最高收益的前缀。

所以我们可以将所有 {Si,ci}\{ S_i ,c_i\}按照 ∣Si∣|S_i| 的大小进行排序,贪心取即可。最后记得加上一开始的 ∑i=1nai×bi\sum_{i = 1}^{n} a_i \times b_i 的值。

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

T5

100%

先考虑计算 f(x)f(x) 的值。

由于 A⊕B=xA \oplus B = x,所以 B=A⊕xB = A \oplus x。

首先可以发现如果 A=xA = x,那么 B=0B = 0,此时是不符合条件的,故实际上 A,BA,B 的范围为 1≤A,B<x1 \leq A,B < x。

设数字 xx 的二进制最高位为 kk(即 2k≤x<2k+12^k \le x < 2^{k+1})。由于 A⊕B=xA \oplus B = x,那么 AA 和 BB 在第 kk 位上必然是一个为 00,一个为 11。

不妨设 AA 的第 kk 位为 11,BB 的第 kk 位为 00。

显然 AA 的范围为 [2k,x−1][2^k ,x-1],接下来我们可以证明 AA 如果取其中的任意一个值都是满足条件的。

也就是说对于范围内的 AA,其对应的 BB 必然满足 B<xB < x,其实这一步十分显然:BB 的二进制第 kk 位是 00,而 xx 的二进制第 kk 位是 11,比 kk 更高的位置二者都是 00,故 B<xB < x。

考虑到 AA 和 BB 在第 kk 位可以互换,所以对于某个 xx,合法的正整数对数 f(x)=2(x−2k)f(x) = 2(x - 2^k)。

接下来我们需要快速计算 ∑i=1nf(i)\sum_{i=1}^n f(i):

不妨设 highbit⁡(x)\operatorname{highbit}(x) 为 xx 的最高位表示的数字,即 f(x)=2(x−highbit⁡(x))f(x) = 2 (x - \operatorname{highbit}(x)) 。

我们要求的是

$$\begin{aligned} \sum_{i = 1}^{n} f(i) &= \sum_{i = 1}^{n} 2 (i - \operatorname{highbit}(i)) \\ &= \sum_{i = 1}^{n} 2i - 2 \sum_{i = 1}^{n} \operatorname{highbit}(i) \end{aligned}$$

其中 ∑i=1n2i\sum_{i = 1}^{n} 2i 可以直接用等差数列求和计算(结果为 n×(n+1)n \times (n + 1)),∑i=1nhighbit⁡(i)\sum_{i = 1}^{n} \operatorname{highbit}(i) 可以通过最高位来计算。

具体来说,我们可以先枚举最高位(假设为 kk),此时最高位是 kk 的数的范围是 [2k,min⁡(2k+1−1,n)][2^{k} , \min(2^{k + 1} - 1, n)],故这一段的求和结果为 2k×(min⁡(2k+1−1,n)−2k+1)2^{k} \times (\min(2^{k + 1} - 1, n) - 2^{k} + 1)。

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

T6

100%

首先有一个非常关键的结论:第一个不能整除区间 LCM 的数字 xx 必然是一个质数的次幂(即 x=pkx = p^k)。

证明: 假设最小的不能整除 LCM 的数 xx 是一个包含不同质因数的合数。那么 xx 可以分解为若干个两两互质的质数次幂的乘积,这些质数次幂都严格小于 xx。因为 xx 是“最小的”不能整除的数,所以这些严格小于 xx 的质数次幂必然都能整除 LCM。而它们两两互质,故它们的乘积 xx 也必然能整除 LCM,产生矛盾。因此,第一个不能整除的数字绝不可能是包含多种质因数的合数。

所以,我们只需要寻找最小的、且其倍数在查询区间 [l,r][l, r] 中没有出现过的质数次幂 pkp^k。 由于 ai≤106a_i \le 10^6,能够成为 aia_i 约数的质数次幂最大不超过 10610^6。大于 10610^6 的最小质数次幂是 10000031000003(它本身是质数)。这意味着对于所有的询问区间,无论其内的元素是多少,10000031000003 这个质数次幂绝对不可能出现在它的因子中。所以,任何询问的最小缺失质数次幂最大就是 10000031000003,答案不可能超过 10000021000002。

考虑先预处理出 10610^6 内的所有数字的质因子。

我们可以离线处理所有询问:

  1. 将所有询问区间按照右端点 rr 从小到大排序。
  2. 建立一棵线段树,维护的值域为 2∼10000032 \sim 1000003。线段树维护区间内的最小值,其中第 ii 个值表示从小到大的第 ii 个质数幂在数组中最后一次出现的位置
  3. 随着指针 rr 向右移动,我们通过预处理好的最小质因子数组在 O(log⁡ar)O(\log a_r) 时间内对 ara_r 进行质因数分解。对于它的每一个极大质因子次幂(例如 pm∣arp^m | a_r),我们将 p1,p2,…,pmp^1, p^2, \ldots, p^m 在线段树上对应位置的值更新为当前的 rr。
  4. 对于右端点正好在 rr 的所有询问 [l,r][l, r],由于我们要找最小的缺失质数次幂,只需在线段树上寻找:从左往右第一个(最小的)其最后出现位置 <l< l 的位置。这一步可以在线段树上二分得到。因为线段树维护了最小值,如果左子树的最小值 <l< l,说明缺失的最靠前质数次幂在左半区,我们就向左递归;否则向右递归。查找到的叶子节点对应的值再减去 11,即为该次询问的答案。

时间复杂度 O(nlog⁡nlog⁡V+Vlog⁡V)O(n \log n \log V + V \log V)(其中 V=106V = 10^6)。