Atcoder Beginner Contest 270(A~Ex)

Good news : Finished A~F in 44 minutes.

Bad news : WA 3 times for A~F and the solution of G is FST.


赛时

A 简单或运算。

B 简单分类讨论(少带了个绝对值挂了一发谔谔)。

C 找树上两点路径,甚至不需要优化。

D 刚开始以为贪心,双方直接取最大值即可,于是挂了两发。但是由于决策有限且不连续,取最大值的决策不一定是最优的。所以我们还是需要 dp。

不妨设 dpi 表示取完 i 个石子之后最后取的人比另一个人多取几个石子。则有转移方程:

dpi=max(dpi,akdpiak)

由于石子总数固定,我们又知道了先手会比后手多取的石子数量,于是最终答案就是 dpn+n2

E 小清新题。我们不妨将 A 看成一个柱状图,则每一轮其实就是从下向上将整个图截断一个单位长度。于是我们可以考虑用一个扫描线从下向上扫,以每一个柱子的高度为关键高度动态记录贡献,最后找到无法再向上扫的位置,暴力轮一遍即可。时间复杂度 O(n)。也可以用二分答案代替从下向上扫,将扫描的复杂度降低为 log。不过复杂度瓶颈不在这里,没有必要。

F 最小生成树,考虑将船坞和机场分别作为一个虚拟节点,对于【不建造船坞也不建造机场】,【建造船坞不建造机场】,【建造机场不建造船坞】,【机场和船坞都建造】分为四种情况讨论,分别求一遍最小生成树,最后取最小值即为最终答案。

G 刚开始没注意到取模,以为 xi 单调递增,还 20min 写了个矩阵倍增查找,写完发现样例过不去,于是 FST 喜加一。后来又觉得复杂度实在不太好优化,又想向根号分治之类的方向想,但也没什么结果。


赛后

G - Sequence in mod P

G 正解还真的沾点根号!

考虑将式子展开:

Xi=(AXi1+B)modP=(A2Xi2+AB+B)modP=(A3Xi3+A2B+AB+B)modP==(AiS+B(Ai1++1))modP=(AiS+BAi1A1)modP=G

我们把所有和 Ai 有关的项全部放到右边,剩下的扔到左边,将等式两边同时乘上 A1 再加 B,则有:

AGG+B=(ASS+B)Ai (modP)

左边的常数看作 x,右边的常数看作 y,则有:

yAi=x (modP)

也就是一个经典的高次同余方程。我们可以采用 BSGS 算法求解。

哈希用 map 实现,时间复杂度 O(TPlogP)

需要注意当 A=1 的时候,上面的式子是不成立的,我们会得到:

Xi=S+iB=G (modP)

此时 i=GSB,作个逆元即可。同样此时也需要判断 B 是否为 0,如果为 0 则需要进一步特判。

除此之外还需要特判一下 X0=S 是否等于 G,以及 A 是否为 0

总结来说,本题的本质实际上就是根号优化,细拆 BSGS 根号优化的本质其实就是一个 meet in the middle。Xi 显然是不好做的,因为我们无法将两个 Xi 的答案拼起来得到另一个 Xi,因为这个式子不满足结合律。于是我们将 Xi 的式子拆开,将高次幂项和其它项分离,发现可以化成一个满足结合律的高次同余方程的形式,于是就可以使用 BSGS 进行根号优化。


Ex - add 1

H 也尝试补了一下。感觉很妙。

题目中的状态是复杂的,且 n 的范围很大,无法状压。但是我们是需要进行状态之间的转移的。

所以我们就需要考虑如何才能高效地表示一个状态。我们都关注哪些信息呢?每个数当前距离 ai 的差值?这太冗余了。事实上,由于本题特殊的性质,我们只需要关注 n 个数中,当前值 ci 距离 ai 最大的差值即可。

很奇怪?但是这却是可以转移的。设这个最大的差值为 s,我们显然可以找到一个 r,使得 ar<sar+1。此时如果我们对于 a1ar 进行之间的某一个数进行了清零操作,由于其他数的值都会加 1,所以我们都 s 就会被更新为 s1;如果我们对于 ar+1an 中的录一个数 ak 进行了清零操作,那么由于 aks,所以此时 s 就会变成 ak

发现了吗?这个状态虽然简洁,但是在找到 r 的情况下,是可以进行转移的。(其实这里用一个简单s 映射一类复杂的状态的设计,有点类似于 hash 的感觉了,个人感觉非常妙)

于是我们设 dpi 表示当前 s=i 时,距离终点最大差值为 0 状态的期望轮数(倒序转移),则初始状态 dp0=0。有转移方程:

dpi=1n(ri×dpi1+j=ri+1ndpaj)+1

我们转移顺序变一致一下,把 dpi1 拉出来:

dpi1=1ri(n×(dpi1)j=ri+1ndpaj)

然后我们发现此时 i 较小的状态是由较大的状态转移过来的,而初始状态好像是 dp0,顺序反了。于是我们考虑将 dp 的意义颠倒一下,设 fi 表示 dpandpi,则有 dpi=dpanfi。考虑将转移方程化为只和 f 有关的式子,则有:

dpanfi1=1ri(n×(dpanfi1)j=ri+1ndpaj)=1ri(j=ri+1n(dpandpaj)+r×dpann×(fi+1))=1ri(j=ri+1nfajn×(fi+1))+dpan

dpan 消去,变号得:

fi1=1ri(n×(fi+1)j=ri+1nfaj)

此时我们发现 dpn 全部消去了,变了个号后 fi 还是从小向大转移,但是由于 fi 的意义和 dpi 正好相反,所以我们就成功改变了转移顺序。此时我们就已经可以正常转移了。

又注意到 n 非常大,所以我们可以考虑采用矩阵加速的方式优化转移,转移过程中以每一个 ai 为关键转移点停止转移找到当前的 r 后再重新开始转移即可。设单次矩阵乘法的时间复杂度为 ω=23,则时间复杂度 O(ωnlogA)

听说还有更高级的优化方式可以进一步优化。不过与我无关(

启发

  1. 【解题】如果看到一个式子,想不到什么优化方式,不妨先将这个式子向后推几步,看看能不能套用什么数学方法进行优化。

  2. 【赛时】仍然是,Think twice , code once.

  3. 【trick】找出基础状态要素之后,优化时不妨考虑将对于答案贡献相似的状态归为一类,或是省略与答案相对无关的状态,抓住影响答案贡献的关键要素设计状态,也许就会大大优化。(或者可以理解为对于每一个状态设计一个合理且有效的 hash 值进行转移,不过这种理解方式应该没有前一种更好)

posted @   ydtz  阅读(59)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示