20260301 ICPC 总结

怎么是公开比赛,那我可以摇巨佬来帮我写题吗。

A - Towers of Boxes

随便推一下,不难算出一座塔至多用 \(X = \lfloor \frac{d}{m} \rfloor + 1\) 个盒子,则答案为 \(\lceil \frac{n}{X} \rceil\)。

B - Eating Game

我们直接枚举从哪个人开始比赛,然后模拟比赛过程,记录有多少位可能成为赢家的玩家即可。

C - Deletion Sort

赛时被恶狠狠地诈骗了。我们不难发现,除去序列原本就是不降序列的情况,一定存在一种删除方案使得最后只剩 \(1\) 个数字(最大的数字)。于是答案非 \(n\) 即 \(1\),判一下就行了。

D - Specialty String

括号序列匹配的弱化版,同种字母是一类括号,左右括号可以自己定。然后用栈模拟这个过程就结束了,虽然 \(n \le 5000\) 但是完全可以 \(O(n)\) 解决。

E - Beautiful Numbers

有一个显而易见的结论:若 \(x\) 为漂亮数字,则一定有 \(F(x) < 10\)。利用这个结论,我们只需要用 DP 随便搞搞就行了。

F - Portal

令两个传送门的位置分别为 \(A\) 和 \(B\)(等同于题目中的 \(x\) 和 \(y\)),我们发现中间 \([A+1,B]\) 这一段数字可以不断循环移动,考虑到字典序的性质,我们把最小的数字移到最前面。

左边 \([1,A]\) 这一段和右边 \([B+1,n]\) 这一段都可以将自身最靠近中间一段数字的值插入另一侧最靠近中间一段数字的部分。贪心来考虑,我们要先确保左边这一段的值都比中间那一段的第一个数字小,于是就不断往右边那一段塞。如果左边这一段的值本来就都比中间那一段小,那可以考虑把右边那一段中比中间那一段的第一个数字小的前缀部分挪到左边这一段。

这样就构造完成了,具体实现时可以用三个数组分别表示左边、中间、右边的三段数字,分开搞会简单很多。

G - Test Generator

我好喜欢多此一举啊我,我赛时怎么把 \(s\) 也拆成二进制位了。。。赛后听老师讲了才反应过来根本不用拆 \(s\)。。。

把 \(m\) 拆成二进制位来考虑。换句话说,我们求出一个 \(k\) 以及满足 \(0 \le p_1 < p_2 < \dots < p_k\) 的 \(p\) 数组满足 \(m = 2^{p_1} + 2^{p_2} + \dots + 2^{p_k}\)。

现在我们要构造一个长度同样为 \(k\) 的 \(q\) 数组,使得 \(s = 2^{p_1} q_1 + 2^{p_2} q_2 + \dots + 2^{p_k} q_k\)。由于按照 \(q\) 来构造 \(a\),最小的 \(n\) 是 \(\max \{q\}\),因此我们为了最小化 \(n\),需要最小化 \(\max \{ q \}\)。

注意到这个东西显然具有单调性,考虑二分。二分 \(\max \{ q \}\) 的值,然后尝试构造——从 \(q_k\) 开始,尽可能用到最多(但是不得超过 \(\max \{ q \}\)),最后判断是否足够凑出 \(s\) 即可。

然后就做完了,代码还是很好写的。

H - Divisive Battle

分析性质,有一个肯定对的结论:如果存在一个 \(a_i\),使得对其质因数分解(\(a_i = p_1^{c_1} + p_2^{c_2} + \dots + p_k^{c_k}\),其中 \(p_i\) 均为质数)后,满足 \(p_1 < p_k\),则 Alice 在第一步操作就可以将 \(a_i\) 拆成 \(\frac{a_i}{p_1}\) 和 \(p_1\),这样无论后面 Bob 怎么拆,由 \(\frac{a_i}{p_1}\) 拆出来的数中肯定有 \(> p_1\) 的,所以 Alice 就赢了。

当然,如果最开始这个数列就是非递减的,那 Bob 肯定就赢定了,因为完全无法操作。

那么,如果最开始这个数列不是非递减的,而又不存在满足第一段结论所述性质的 \(a_i\),Alice 和 Bob 究竟谁能赢呢?注意到这个时候任意 \(a_i\) 都可以被表示为 \(p^k\)(其中 \(p\) 是质数),我们考虑数组 \(q\) 使得 \(q_i\) 为 \(a_i\) 唯一的质因子,显然,如果 \(q\) 是非递减的,则 Bob 赢,否则 Alice 赢。

I - Divisibility Game

博弈???这场的两个博弈题怎么都是这种找性质的题。。

我们把每个 \(b_i\) 分类:黑色的,只有 Alice 能用;白色的,只有 Bob 能用;灰色的,Alice 和 Bob 都能用。分别求出其个数(令黑色的有 \(a\) 个,白色的有 \(b\) 个,灰色的有 \(c\) 个),显然两人都会优先用灰色的,灰色的用完了再用黑或白色的,于是 Alice 能坚持 \(A = a + \lceil \frac{c}{2} \rceil\) 回合,Bob 能坚持 \(B = b + \lfloor \frac{c}{2} \rfloor\) 回合,不难发现若 \(A > B\) 则 Alice 赢,否则 Bob 赢。

于是现在题目就变成了如何判断一个 \(b_i\) 究竟是黑白灰中哪种颜色,考虑用 \(a_i\) 去造。具体地,记录 \(t_x\) 表示 \(x\) 这个数是多少个 \(a_i\) 的倍数,则对于每个 \(b_i\),判断:如果 \(t_{b_i} = n\) 则是黑色,如果 \(t_{b_i} = 0\) 则是白色,否则是灰色。

\(t_x\) 怎么求?由于 \(\max\{a\}\) 和 \(\max \{b\}\) 的上限都是 \(n+m\),可以枚举每个 \(a_i\) 的所有 \(\le n+m\) 的倍数 \(x\) 并让 \(t_x \gets t_x+1\)。这样做的时间复杂度很炸裂,但是我们只需要对 \(a\) 去重,就是调和级数,\(\log\) 能接受。于是就做完了。

J - Mooclear Reactor 2

我们维护 \(dp_k\) 表示除自身外至多只能选 \(k\) 个物品,且这些粒子的“反应性”都 \(\ge k\) 的情况下,能收获的最大能量和。

先对 \(a\) 按“反应性”\(y\) 倒序排序,并枚举 \(k\) 从 \(n\) 到 \(0\)。维护一个优先队列以及一个指针 \(now\)(初始为 \(0\)),先把 \(a\) 中所有 \(y \ge k\) 却还没进过队列的数塞进队列,并实时维护 \(sum\) 表示当前队列中所有粒子的能量之和。当然,我们还需确保优先队列中的元素个数不得超过 \(k+1\),因此我们不断将能贡献的能量最小的粒子弹出队列。

这个时候的 \(sum\) 表示的是当选择粒子中的“反应性”都 \(\ge k\) 且至多选择 \(k+1\) 个粒子时能收获的最大能量和。我们让 \(Mx = \max \{sum\}\) 即全局最优解。

当然,我们还需要维护 \(dp_k\)。由于 \(dp_k\) 是为后续处理商店里的粒子使用情况而预处理的,因此 \(dp_k\) 只能选 \(k\) 个元素(要为最后那个商场里的粒子预留位置),只要当前队列中的元素个数 \(> k\),我们就让 \(dp_k\) 为 \(sum\) 减去当前队列中最小的能量,否则 \(dp_k = sum\)。注意这个时候并不需要弹出队列中数值或修改 \(sum\) 的值。

为了方便上述维护,我们的优先队列的队顶一定要是最小的值,也就是说它是一个小根堆——这很简单,我们用 priority_queue<LL,vector<LL>,greater<LL>> 定义不就完事儿了。

于是我们就把所有 \(dp\) 都预处理出来了,并获知了在不考虑商店里的粒子的情况下的全局最大能量和 \(Mx\)。若商店里的粒子能产生能量为 \(x\),“反应性”为 \(y\),则其答案就是 \(\max(Mx,dp_{y} + x)\) 了。

Summary

H 没做出来挺可惜……其实最开始那个结论我也想到了,但我不敢想大部分 Alice 赢得情况都源于这个结论,我以为有更复杂的过程。当然我赛时也没考虑过后面那种 \(a_i = p^k\) 的情况……

I 也没多难,感觉主要就是想到了对 \(b_i\) 分类就能做出来吧。调和级数这一块还是比较显然的……

J 很有意思,用优先队列维护然后 DP 预处理最后 \(O(1)\) 回答的思路真的很巧妙!做不出来就累积一个 trick 呗,之后再遇到就会了。

只剩最后一天了,圆我一个 AK 梦吧。

posted @ 2026-03-02 11:51  嘎嘎喵  阅读(61)  评论(0)    收藏  举报