CSP2020 题解

\(A\)

找循环节模拟即可。

时间复杂度 : \(O(1)\)

\(B\)

答案是 \(2\) 的若干次方减去 \(N\)

对于 \(K = 64\) 的情况 , 可能会溢出 \(long \ long\) , 注意到 \(2 ^ {64} = 18446744073709551616\) (可以用计算机自带的 "计算器" 软件算出)。

于是对这种情况单独特判即可。

时间复杂度 : \(O(N)\)

\(C\)

直接维护是不现实的。

对于初始的值和每个 "加法" 操作 , 其贡献必然为其值乘上后面出现的所有乘法操作的值。

那么直接计算出每个操作后面的函数对它乘了多少 , 这可以通过一遍反向拓扑排序或记忆化搜索得到。

但这样做没有考虑 \(3\) 操作中后面乘上的数对前面加法操作的影响。 因此不妨打上标记 , 再做一遍正向的拓扑排序。 把这些操作的贡献一起计算。

时间复杂度 : \(O(N)\)

\(D\)

结论 : 如果最大的数减去最小的数后比次大的数还要大 , 那么就直接减去。

证明 : 假设大小关系 \(A < B < C < D\)。 有 \(D - A \geq B\)。 若 \(C\) 减去了 \(B\) , 那么就有 \(C - B < D - A\) , 这样 \(C\) 就必然会比 \(D\) 先淘汰 , 所以 \(C\) 不会选择减去 \(B\) , 故将 \(D\)\(A\) 是不劣的。

接着 , 若最大的数减去最小的数后成为了最小的那个数 , 那么问题就转化为了 \((N - 1)\) 时的情形 , 可以递归处理。 终止条件是只剩下两个数或出现了第一种情况。 在这个时刻到来时 , 判断奇偶性即可。如果是奇数那么产生 \(1\) 的贡献。

最简单的维护方式是采用 \(std :: set\)。 但是太慢了。

考虑优化 , 不难发现具有隐含的单调性。 也就是说 , 如果把未使用的数放入一个队列 , 减去后新生成的数放到另一个队列中。 那么这两个队列中元素必然都单调递增。

这样做的时间复杂度 \(O(N)\)

posted @ 2020-11-20 23:38  evenbao  阅读(321)  评论(0编辑  收藏  举报