AtCoder AGC003 简要题解
阅读原文时间:2023年07月09日阅读:1

A

首先横向和纵向互相独立,因此只考虑横向的情况。

那么显然只要不只往一边走都一定存在一种构造方式,直接判断即可,复杂度 \(\mathcal{O}(|S|)\)。

B

首先相邻两个数同时配对两次可以等价于两个数分别与自己配对两次。

因此相邻两个数至多配对一次,于是我们可以将所有数先把 \(3\) 以上的部分去掉,然后就可以直接 \(\rm dp\) 了。

当然你也可以继续观察,你会发现可以把所有数调到 \(1\) 及以下,这时显然可以直接贪心。

C

首先观察一点性质:

  • 操作一必然将其涉及的两个数下标奇偶性翻转;操作二对其涉及的两个数下标奇偶性不变。

由于数字两两不同且仅关注相对关系,因此不妨先将数组离散化成一个排列。

为了最终使得排列有序,我们必须使得所有 \((p_i - i) \equiv 1 \pmod{2}\) 的 \(p_i\) 下标与其奇偶性相同,那么就需要借助操作一。

此时我们又有观察:

  • 奇数元素和偶数元素下标奇偶性不同的个数相同。

同时我们可以通过二操作将任意一个元素移动到下标奇偶性相同的位置。

因此最优策略一定是将两个奇偶性不同且需要调整下标奇偶性的元素一起翻转奇偶性,且根据上述调换观察一定能将这样两个数移动到相邻位置。

因此答案就是 \((p_i - i) \equiv 1 \pmod{2}\) 的数量的一半,复杂度 \(\mathcal{O}(n \log n)\)。

D

注意到这本质上是一个带有特殊性质的最大独立集问题,因此肯定要从非指数级暴力出发来优化。

对于每个数,我们显然只关心其每个素数上次幂 \(\% 3\) 的取值,我们将 \(a\) 进行次幂 \(\% 3\) 变换后的数为 \(f(a)\)。

那么 \(\forall a, b\) 不能和 \(a\) 同时选当且仅当 \(f(a) \times f(b)\) 为完全平方数。

此时有观察:

  • 对于确定的 \(f(a)\) 可以发现 \(f(b)\) 唯一确定。

对于 \(f(a)\) 中不含的因子 \(f(b)\) 中一定也不含;否则 \(f(b)\) 在该因子上的次幂一定与 \(f(a)\) 在该因子上的次幂和为 \(3\)。

那么我们只需要把每个数 \(a\) 给 \(f(a)\) 产生贡献,然后把冲突点对 \((f(a), f(b))\) 取出贡献较多的即可。

于是现在的瓶颈在于 如何分解质因数。

当然你大可使用 \(\rm Pollard-Rho\) 进行分解,复杂度 \(\mathcal{O}(ns ^ {\frac{1}{4}})\),这里采取了一个不用 \(\rm Pollard-Rho\) 的做法,可能在某些题上有奇效。

我们考虑首先筛出每个数 \(\le s ^ {\frac{1}{3}}\) 的质因子,那么此时每个数必定为一下几种形态:

  1. \(x = p\)
  2. \(x = pq\)
  3. \(x = p ^ 2\)
  4. \(x = 1\)

显然后两种可以直接判断出来,于是考虑如何区分前两者。

在本题当中,第二种显然不可能与任何数相冲突,因此可以直接选。

若第一种 \(x = p > s ^ {\frac{1}{2}}\) 那么显然也可以直接选,否则我们能断定 \(x\) 必为质数,因为 \(p, q > s ^ {\frac{1}{3}}, pq > s ^ {\frac{2}{3}} > s ^ {\frac{1}{2}}\)。

这样就在 \(\mathcal{O}(n \frac{s ^ {\frac{1}{3}}}{\ln s} + n \log n)\) 的复杂度内解决了本题。

E

首先不难有观察:

  • 若 \(q_{i - 1} \ge q_i\) 那么这样操作可以等价于 \(q_{i - 1}\) 这一步没有操作直接操作 \(q_i\)。

因此我们可以使用单调栈求出一个 严格 上升的操作序列,这样序列只会不断变长。

貌似接下来没有思路了?不妨首先来考虑一下暴力怎么做。

显然我们肯定要得到一个跟值域大小非多项式相关的做法,不然没啥优化前途。

考虑逐步模拟这个操作,令 \(f_{i, j}\) 表示进行完第 \(i\) 个操作后,\(j\) 这个数的个数,\(g_{i, j}\) 表示最终序列 \([1, i]\) 内 \(j\) 的数量(由于操作序列严格递增,因此每次操作不会影响到上一次操作之前的数)。

那么不难发现转移:

\[f_{i, j} = f_{i - 1, j} \times \lfloor \frac{q_i}{q_{i - 1}} \rfloor + g_{q_i \% q_{i - 1}, j}
\]

瓶颈显然在于优化后半部分,考虑怎样求出后半部分使其复杂度与值域无关。

观察一下要求的形式,因为 \(d = q_i \% q_{i - 1} < q_{i - 1}\) 因此我们将这个任务迭代给 \(i - 1\) 次操作去完成。

而对于 \(i - 1\) 而言,若 \(d \le q_{i - 2}\) 那么显然还可以将这个任务迭代给 \(i - 2\) 去完成;否则必定有:

\[g_{q_i \% q_{i - 1}, j} = f_{i - 2, j} \times \lfloor \frac{d}{q_{i - 2}} \rfloor + g_{d \% q_{i - 2}, j}
\]

容易发现这样可以不断迭代下去,复杂度 \(\mathcal{O}(nq ^ 2)\),考虑优化这个暴力。

不难发现在迭代的过程中有很多部分是冗余的,因为它没有造成贡献而是将任务直接甩锅给前一个操作,考虑压缩枚举这些只甩锅的部分。

因此对于一个 \(d\),我们找到满足 \(q_a \le d\) 最大这样的 \(q_a\),然后就有转移:

\[g_{d, j} = f_{a, j} \times \lfloor \frac{d}{q_a} \rfloor + g_{d \% q_a, j}
\]

分析一下复杂度:每次 \(d\) 都会对一个 不大于 其的数取模,因此每次数值减半,复杂度 \(\mathcal{O}(qn \log W)\)。

容易发现现在复杂度瓶颈在于状态,状态数本身就是 \(\mathcal{O}(qn)\) 的,考虑优化。

事实上,我们并不需要知道 \(f_{1 \sim q - 1}\) 的具体值,只需要知道 \(f_q\) 这一个位置的值即可。

我们把需要计算的节点和转移边全部建图表示出来(因为不同数值在转移中实际上基本一致,因此我们只考虑第 \(i\) 次操作所有数值是如何转移的),有如下观察:

  • 这张图一定形如:一条主链从下至上依次为 \(f_1, f_2, \cdots f_q\);对于主链上 \(\forall i\) 有 \(i\) 往下连接了至多 \(\log W\) 个点构成侧链 \(g_{x_1}, g_{x_2}, \cdots g_{x_k}\)。

  • 对于主链上的点 \(i\),其一定由 \(f_{i - 1}\) 与其最顶端的侧链转移而来。

  • 对于侧链上的点 \(i\),其一定由主链当中一个点 \(f_x\) 和其下方紧接着的一个侧链转移而来。

  • 根据 \(\rm dp\) 这张图为一个 \(\rm DAG\),且节点数和转移数为 \(\mathcal{O}(q \log W)\)。

如果要沿着边依次往上推,那么必须带着后面的数值一起做,就相当于模拟上面的暴力 \(\rm dp\)。

那么考虑一下贡献来源在哪里:不难发现为 \(f_1\) 和所有侧链底端的状态。

我们在建图过程中可以求出这些点会对哪些数值产生贡献,不难发现一定是一段前缀,且贡献系数为这个点到根(即 \(f_n\))的带权路径和。

于是我们在 \(\rm DAG\) 上 \(\rm dp\) 求出每个点到根的带权路径和,就可以直接计算贡献了,使用差分维护前缀加。

分析复杂度发现瓶颈在建图时需要查找最后一个不大于一个元素的数,因此复杂度为 \(\mathcal{O}(q \log W \log q)\)。

实现的时候可以不需要真的写出 \(\rm DAG\) 上 \(\rm dp\),易知每个点到根的贡献系数和也为反图上根到这个点的贡献系数和。

不难发现建图的过程也是一个拓扑序,因此可以在建图的过程中同时 \(\rm dp\) 出答案。

F

考虑第二层分形哪些联通块之间会联通。

不难发现加入第一分形左右相邻时,若一行开头和结尾均为黑色,就会合并两个联通块,上下相邻类似。

若一行开头和结尾均为黑色,我们不妨将其称为「行接口」,类似地定义「列接口」。

由于行接口和列接口是否存在会带来纵向和横向的联通性,因此我们根据其存在性分类讨论。

行接口,列接口均存在时。

不难发现二分形当中相邻两个黑格都会通过一种接口联通,因此二分形当中所有黑格都是联通的。

那么我们大胆猜测 \(k\) 分形当中所有黑格也是联通的。

证明考虑 \(k\) 分形每个相邻的 \(k - 1\) 分形,其中一定存在一种接口使得其能联通。

因此不论 \(k\) 为多少,这种情况下答案均为 \(1\)。

行接口,列接口均不存在时。

类似地可以证明在任意 \(k(k > 1)\) 分形当中,任意两个相邻的 \(k - 1\) 分形之间都不存在连通块可以联通。

因此这种情况下答案即为:\(b ^ {k - 1}\)(其中 \(b\) 为一分形中黑格数量,注意特判 \(k = 0\) 的情况)

行接口,列接口恰好仅存在一种时。

显然两种接口等价,因此只考虑仅存在行接口的情况。

不难发现二分形当中仅有横向相邻的一分形会联通,并且容易归纳得任意的 \(k(k > 1)\) 分形当中仅会有横向 \(k - 1\) 分形联通。

此时容易发现 \(k\) 分形当中的连通块数量可以由 \(k - 1\) 分形当中的连通块数量通过简单转移得出。

不难发现一次分形变换相当于:将若干个位置替换为 \(k - 1\) 分形,横向相邻 \(k - 1\) 分形之间可以通过接口减少连通块数量。

并且我们有观察(不难证明):

  • 在 \(> k\) 的分形变换中 \(k\) 级分形内部的连通性保持不变。

那么转移就很简单了,令 \(f_i, g_i\) 表示 \(i\) 级分形的联通块数量和左右接口数量,\(a, b\) 分别为给定矩形横向相邻黑色格子的数量和黑色格子数,\(c\) 为给定矩形横向接口数量,那么有转移:

\[f_i = f_{i - 1} \times b - a \times g_{i - 1}
\]

\[g_i = g_{i - 1} \times c
\]

不难发现这是一个常系数齐次线性递推,使用矩阵加速,复杂度 \(\mathcal{O}(nm + \log k)\)。