「loj - 2850」「ROI 2018 Day 2」无进位加法
以前以为自己会证时间复杂度,后来考到原题发现自己证伪了,草。
从高到低确定 的每一位是否可以为 。
枚举第 位是否可以为 时,比第 位低的位全部填 ,比第 位高的保留不变,得到一个 。之后看是否存在一个 满足要求。
相当于我们需要把 的每个 分配给某个 (也即, 的这一位为 ),使得 。
简单的观察:不妨设 ,则存在一个最优解满足 。
由观察,考虑 最高位的 ,它一定分配给最大的 。
如果 的最高位 大于 的最高位 ,则 接下来不需要被分配其他的 ,直接删掉。
如果 的最高位 等于 的最高位 ,则需要把 删去最高位后再塞回去(如果删掉最高位后非零的话)。
如果 的最高位 小于 的最高位 ,则不合法,此时 的第 位填 。
当然,如果把所有 都删完了,则 的第 位填 。
显然,这一过程不需要每次都从最高位开始扫 ,比 高的位的影响保留下来,可以从第 位开始往后扫。
某时刻的某个 一定是初始时的某个 删去最高的若干个 的情况,因此在过程中 的可能情况只有 种。
可以将这 种可能的 拿出来排序,具体来说由于只有长度相同的需要排,做个基数排序即可(当然,由于这部分不是瓶颈,你也可以尝试一些 的排法)。
考虑某一时刻枚举到 的第 位。
设此时 ,并设 的最高位为 。则合法的一个必要条件为 。
分配给 的 最大也只能是 ,还有可能因为前面的数需要删去最高位重新塞回来而变小。
另一方面,合法的一个充分条件为 。
此时所有数都可以直接被删掉。
那么事实上需要检验的只有 的情况。
我们找到使得 最大的 中最小的 。
如果 填 ,则 分别对应了 的第 位上有 。
删掉 ,插入 删去最高位后的 ,然后继续找 。
如果 ,则前面的合法。
如果 ,则前面的不合法。
如果 ,我们令 ,令 为此时使得 最大的最小 ,然后继续递归检验。
可以使用线段树维护查找最大值的过程。
然后可以证明,这样递归的总次数不会超过 。由于使用线段树维护,总复杂度为 。
首先,相同长度的 只会有一个最大的 。也即,我们每次选定的 比上次递归进来的 对应的长度要短。
因此,如果最开始需要检验的是 ,则递归次数实际上不会超过 。
而对于每个串,它只有一次是“最开始”检验的。因此得证。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现