#9134. 翻转硬币 题解

首先考虑一些简单的情况,比如 m=1

容易发现操作 1 和操作 2 的顺序不会影响结果,于是可以钦定所有操作 1 在操作 2 之前。并且可以发现,进行完所有 1 后 2 的次数即为 (连续段个数1)

然后考虑将 m>1 的情况。显然最后序列上每 m 长度分一段,则每一段都相同,最后一段例外,是和其他段的一段等长前缀相同。那么设最后每段都为 S,一开始每段的状态为 Ai,则在所有操作 2 之前,都有 S=AiS=flip(Ai)flip(X) 表示把 X 串内所有数 1。然后定义一个序列 ci 表示第 i 段有没有被 flip。则与 m=1 时一样,需要进行操作 2 的次数即为 c 的连续段个数。

上面的是 naive 的,相信大家赛时都想出来了。

然后考虑如何解决这个转化后的问题。如果考虑 dp,则会发现不管将这个状态和操作 1 还是 2 联系起来,都会对另一种操作有后效性。很难设计状态。贪心什么的就更难了。

此时发现我们的路已经被堵死了。那就要从头开始考虑这个问题。

我们观察一下数据范围,n300。很像一个 n3 的问题。但是刚才已经基本否定了常规解法。

你突然想到 m 长度一段,就共有 nm 段。看到这个分数,联系 n300,你发现 n20<log106。你发现你可以根号分治!

  • mn

则上文的 S 长度 20。暴力状压 S,对于每一种 S,考虑 dp。设 dpi,0/1 为当前处理到第 i 段,有没有翻转的最小操作数。则有:

dpi,j=min(dpi1,j+popcount(Sci(j×(2m1)),dpi1,j1+popcount(Sci(j×(2m1)))+1)

其中 (j×(2m1)) 部分是要看这一段是否翻转,+1 则是因为新增连续段。

初始状态为 dp0,0=0

最后一个不完整的段要特殊处理,差别不大。

  • m>n

则段数 20。暴力状压 c,然后处理 S。根据 S 当前位 0/1 的数量,贪心地选择更小的,再加上操作 2 次数。全部取最小值即为答案。

时间复杂度 O(2n×n)。挺稳的。

以上内容纯属杜撰。

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

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示