NWERC 2020 题解

和主席 VP 玩了一下,打了 8 题,只能说主席太强了。

比意想中的要简单一点,而且有两道随机化题。

A - Atomic Energy

考虑一个暴力 dp:设 \(f(i)\) 表示中子数为 \(i\) 的原子可以产生的最小能量。那么在 \(M\) 以内的 dp 值是可以 \(O(M^2)\) 预处理的。

注意到 \(k\) 很大,而 \(n\)​ 很小。考虑背包问题的一个假贪心:每次选“性价比”小的。一般情况下,组合起来可能不是最优的。然而当我们的容量很大时,我们可以在一个限度内施展这样的贪心。由于每个物品的体积都比较小,所以“组合更优”不会在大范围出现。

对于本题,设阈值 \(M=n^2\)(这个值不一定最优,是平方算法可以承受的较大值)。然后 \(O(M^2)\) 预处理小范围的 dp,对于 \(k\) 很大的情况可以先一直一个性价比最小的,直到在 \(M\) 以内直接拼上 dp 值。这样复杂度是 \(O(M^2+q)\) 的。

C - Contest Struggles

签到。答案为 \((d\times n - k \times s) \div (n-k)\)​。在 \([0,100]\) 内合法。

D - Dragon Balls

限制很宽,有很多种做法。

这里是个好写的做法:考虑随机一个点,算出距离 \(d^2\)。考虑这个 \(d^2\) 肯定是根据勾股定理算出来的,那么我们只要得到 \(a,b\) 两个整数满足 \(a^2+b^2=d^2\),然后在随机的那个点周围 \(8\) 个方向上都测一遍。

实测这样得到的 \((a,b)\) 最多三十多组,并且随机情况组数很少。所以一千次是绝对足够的。

\(d^2\) 可以达到 \(10^{12}\) 级别,但 \(a, b\) 只有 \(10^6\)​ 级别,所以不会有超时问题。

E - Endgame

首先考虑一个简单问题:给定始终点 \(A, B\),判断 \(A\) 能否操作两次吃掉 \(B\)。这个比较简单,用一个 set 记录所有操作,然后枚举第一次操作,尝试配对所求第二次操作。这样可以 \(O(n\log n)\) 完成一次判断。当然可以强行优化到更快。

实现上面从操作之后可以判断 Alice 是否能赢。但是之后是否存在 tie 的位置似乎没什么好办法,对于 \(n\) 比较小我们可以逐一测试,但是肯定是过不了的。

我们发现一个很离谱的事情就是,棋盘是 \(n \times n\) 的,而操作种类是 \(n\) 个。为什么都是 \(n\)\(n\) 个操作可以拼出 \(O(n^2)\)​ 个位置,但绝(除了 \(n=2,3\) 的小数据)不会占满整个棋盘,而且冷静分析有相当一部分位置都是空的。

我们考虑随机化:每次随机一个点,判断是否可以 tie。由于随机很多次都点不到的概率是极低的,所以很快就能找到解。

官方题解指出空位的规模是 \(n^2/2\),因此期望两次出解。但是我不知道怎么来的,一个较简单的 \(n^2/4\) 的构造是 \((1, 0), (2, 0), \cdots, (n/2, 0), (0, 1), (0, 2), \cdots, (0, n/2)\)

F - Flight Collision

要求快速模拟整个过程,实际上只需要我们正确模拟就行了,因为每个坠毁时间只会在一对飞机上发生一次。

要正确模拟,只要让一个个坠毁事件按时间顺序发生,显然这样不会出现任何跨越的情况,其间飞机间的相对位置也不会改变。

考虑用 set 或链表维护存活的飞机,用堆维护接下来可能发生的坠毁事件。复杂度 \(O(n\log n)\)

G - Great Expectations

完全不会这种带环的期望题。

从容错的角度考虑状态设计:我们需要比 \(r\) 小,而 \(n\) 是不得不消耗的花费,那么最多可以承受 \(r-n-1\) 的失误代价和。设 \(f(i,j)\) 表示将要到达第 \(i\) 个关卡,以及消耗了 \(j\) 的容错,走到终点需要的期望时间。

可以发现的是,如果真的要重开,那一定是刚刚失误被卡了一下的那个时刻。那么有方程:

\[\begin{aligned} f(i,j) & \leftarrow (f(i+1, j) + t_{i+1}-t_i) & \times p_i \\ f(i,j) & \leftarrow \min(f(i+1, j) + t_{i+1}-t_i + d_i, f(0, 0)) & \times (1-p_i) \\ \end{aligned} \]

其中 \(f(0,0)\) 是起点的期望,代表重开,同时也是我们要求的答案。

我们试一个答案 \(v\)​​,并在方程中用 \(v\)​​ 代替 \(f(0,0)\)​​ 计算,并用最后得到的 \(f(0,0)\)​​ 比较。如果 \(f(0,0)\)​​ 较大说明答案会比 \(v\)​​ 更大,反之同理。我也不知道为什么会这样。

最后二分答案即可。复杂度 \(O((r-n)m \log \text{ans})\)

H - Hot Springs

把所有数组放到一个数轴上。可以发现,我们从中间位置开始,左右横跳,越跳越远,这样必然可行。

那么我们找到中位数,然后分成两部分,轮流输出即可。

I - Island Tour

考虑 \(O(n^4)\) 暴力,枚举三个人的位置 \(i, j, k\),然后检查每个位置是否都不冲突。如果 \(i, j\) 两个人中 \(j\) 先到某位置 \(p\),那么 \(j\) 离开 \(p\) 的时间不应大于 \(i\) 到达 \(p\) 的时间。

VP 时主席写了个这样的暴力,然后加了个超过时限就输出无解摆烂,结果真的 AC 了。之后猜了猜,如果有解,那么 \(i=1\) 时也必然有解,结果加个 assert 也过了。这玩意也不知道怎么证,也可能是假的。如果有人能给个证明可以在 这里 或者评论区说两句。

但其实靠谱做法非常简单:观察到我们要判的只有 \(O(n^2)\) 种本质不同的位置对,那么只有 \(O(n^3)\) 预处理是否合法即可。最后求解也是 \(O(n^3)\)

J - Joint Excavation

很好玩的题。官方解法也非常妙。

考虑直接 DFS。DFS 过程中的点我们分为三类:(一)从未访问的点,(二)DFS 栈中的点,以及(三)曾经访问过但不在栈中的点。曾经访问过就是经历过回溯操作的点。

一个神奇的观察:三类点中,(一)类和(三)类间不相邻。具体证明非常显然:考虑 DFS 的过程,如果存在这条边,那么当时不可能直接回溯而会直接进入那个未访问的点。

注意(二)类点刚好可以构成一条点不自交的路径,那么最后在 DFS 中某时刻出现(一)类点和(三)类点数目相同时遍求得了一组解。

K - Keyboardd

检查所有小写字母及空格,把多的输出即可。

posted @ 2021-10-31 15:47  -Wallace-  阅读(501)  评论(0编辑  收藏  举报