Harbour.Space Scholarship Contest 2021-2022 (Div. 1 + Div. 2) 题解

A - Digit Sum

答案 \(\left\lfloor \tfrac{n+1}{10} \right\rfloor\)​​​。

B - Reverse String

\(O(n^3)\) 暴力比对即可,或者 KMP \(O(n^2)\)

注意对于一个开始位置,向右走的时候不一定走的越多越好,大叉点。

C - Penalty

既然要尽快结束,必然要使 ? 完全倾向某一方,实现对另一方的快速吊打。

于是模拟两遍即可。

D - Backspace

将位置按奇偶分类,\(t\) 中相邻两个元素在 \(s\) 中的位置的奇偶性不同。然后套用序列自动机的手法即可。

注意如果从前往后扫,还枚举开头位置奇偶性做了两次的话,必须要判末尾多余字符是否能用 backspace 删完全,大叉点。

E - Permutation Shift

如何对于一个排列计算还原升序的最小交换次数?注意不是相邻交换,所以和逆序对关系不大。考虑将排列表示为置换环,那么交换次数为,\(p_i\ne i\)\(i\) 的数量减去大小为 \(x\ge 2\) 的环的个数。这显然可以 \(O(n)\) 计算。

然而如果对于每个 \(k\in [0, n)\) 都模拟一遍需要 \(O(n^2)\) 的时间。但实际上我们不需要模拟每个 \(k\)。考虑 \(\text{cnt}_k\) 表示 \(k\) 长度位移之后满足 \(p_i=i\) 的位置数,易得 \(\sum_k \text{cnt}_k = n\)。这说明如果一个 \(k\) 的对上的位置过少,似乎并不值得去做一边模拟。一个 \(k\) 值得我们去尝试,当且仅当 \(\text{cnt}_k\ge n-2m\)

观察到题中额外看似特意构造的限制 \(m\le n/3\),我们带入上式,发现只有 \(3\)\(k\) 值得去尝试。直接模拟这三个 \(k\) 复杂度 \(O(n)\)

F - Pairwise Modulo

首先有一个必要的取模式子的转化:\(x\bmod y = x - y\lfloor\tfrac x y\rfloor\)​。然后把这个式子拆成 \(4\)​ 个部分分开计算和维护。对于当前计算 \(p_i\)​(记 \(\max_i a_i = A\)):

  1. \(\sum_{j<i}a_j \lfloor \tfrac{a_i}{a_j} \rfloor\)​:考虑整除分块,\(\lfloor \tfrac{a_i}{a_j} \rfloor\)​ 只有 \(O(\sqrt a_i)\)​ 种取值,然后我们需要一种可以快速统计前 \(i-1\)​ 个数中 \(\in[l,r]\)​ 中的数之和就搞定了。由于更新操作较查询显然更少,于是采用值域分块的技巧,修改 \(O(\sqrt A)\),查询 \(O(1)\)。那么这一部分复杂度即为 \(O(\sqrt a_i)\)
  2. \(\sum_{j<i} a_i = (i-1)a_i\)
  3. \(\sum_{j<i}a_i \lfloor \tfrac{a_j}{a_i} \rfloor\)​​​:考虑根号分治:如果 \(a_i > \sqrt{A}\)​​​,暴力枚举 \(a_i\)​ 的倍数,复杂度 \(O(\sqrt A)\)​;如果 \(a_i\le \sqrt A\)​,那么考虑时刻维护一个 \(\text{rec}_x\)​,表示前 \(i-1\)​ 个数中 \(\bmod x\)​ 的结果之和。可以根号复杂度维护,\(O(1)\) 取值。
  4. \(\sum_{j<i} a_j\):维护前缀和即可。

总复杂度 \(O(n\sqrt A)\)

G - Common Divisor Graph

突破口:答案 \(\in \{0, 1, 2\}\)​。原因很简单:\(a_s, a_s(a_s+1),a_t, a_t(a_t+1)\) 四个数中至少存在两个偶数,可以由公共因子 \(2\) 联立起来,其中有两个点是新构造的。那么关键就是判断 \(0,1\) 了。

考虑维护出原图中的连通性。不难想到对每个质数 \(p\) 都建一个虚点,并对所有含有质因子 \(p\) 的连边。并查集维护即可,这样可以判断是否为 \(0\)

考虑答案如果为 \(1\),等价于存在一个 \(x\),满足新建 \(a_x(a_x + 1)\) 后,\(a_s, a_t\) 所在连通块被其质因子直接联立,注意这没有传递性,无法直接用并查集维护。注意到联立过程实际上在干什么:

  1. 枚举质因子 \(q|a_x, r|(a_x+1)\),联立 \(q,r\)
  2. 枚举质因子 \(q|(a_x+1), r|(a_x+1)\),联立 \(q,r\)。这一步漏掉容易 WA on 15。

由于一个数的质因子个数规模不大,小于 \(O(\log a)\)​,于是暴力枚举即可,将得到的数对(对应到并查集的根) \((q,r)\)​,记录到一个 std::set 中。查询时判断 set 中对应数对是否存在即可。复杂度据官方题解是 \(O((n+q)\log^2 a)\)​。

H - XOR and Distance

如果对所有 \(x\) 求出答案的话,可能需要我们维护出答案,于是考虑一个数据结构,比如 Trie。

用 Trie 一次性统计答案是很简单的事情:维护出当前区间中最小和最大的元素的值以及答案,和某些 simple 线段树是一样的。但是存在一个问题:异或操作对应到 Trie 上就是交换一层的左右儿子,直接对值的维护如果重新计算可能略有繁琐。于是我们维护与区间左端点距离最近或最远的元素的距离,可以方便避免这个问题。

如果说一次只是交换一个结点的儿子是很好做的,但是直接对 \(x\in[0, 2^k)\) 顺序求,交换数的规模就不可接受了。题解给出了一个机智的技术:格雷码。也就是说我们可以每次只交换一个位。然而我们发现最下层点数最多,应该尽量少得操作,可能需要将格雷码倒置一下。

由于第 \(i\) 层有 \(2^i\) 个点,共有 \(2^{k-i}\) 次操作,于是复杂度为 \(O(2^k\cdot k)\)

I - Stairs

咕咕咕

posted @ 2021-07-23 18:55  -Wallace-  阅读(258)  评论(0编辑  收藏  举报