题解 CF1553F Pairwise Modulo

题意

给定长度为 n 的数列 a

定义 pk=1i,jkaimodaj。你需要输出 p1,p2,,pn

2n1051ai3×105,保证 a 中的元素互不相同。


初步解法

首先看一眼应该能想到显然的 O(nnlogn) 的做法。

我们从 1n 计算 pk。对于每个算到的 k,我们只要计算 1,2,,k1k 之间产生的贡献。考虑正在计算 i(1ik1)k 的贡献。

  • ai<ak 时,有 aimodak=ai。我们把小于 akai 累加起来,树状数组即可。考虑 akmodai 的值,你会发现这和 P2261 [CQOI2007]余数求和 很相似,所以我们套用它的整除分块,在计算时要用树状数组统计符合区间的个数。此部分复杂度 O(nlogn)

  • ai>ak 时,有 akmodai=ak。我们求出大于 akai 个数,树状数组即可。考虑 aimodak 的值,aimodak=aiaiak×ak,所以我们只要计算 aiak 的和。考虑区间 [ak×j,ak×(j+1)1] 之间的数贡献为 j,所以枚举每个区间,树状数组计算个数。由于 a 互不相同,复杂度是均摊 O(log2n) 的。

总复杂度 O(nnlogn)。提交上去!

Time limit exceeded on pretest 7 [pretests] 

优化解法

发现瓶颈是整除分块的 n,考虑把它替换掉。也就是考虑 akmodai(ak>ai) 的另一种算法。注意到正着做是 O(nlogn),倒着却 O(log2n)。那么能不能在计算 ai 的时候就算好 ak 呢?自然是可以的。

在计算 ai 的时候,再用一个数据结构维护桶,与上面的方式类似,找到 [ai×j,ai×(j+1)1] 区间,容易发现这一段区间 ai 的贡献是 ai×j,所以对这一段区间加上 ai×j。在到 ak 时,查询一下 ak 这个点的权值,在答案中减掉即可。

容易发现区间总个数仍然是 O(nlogn) 级别。这个数据结构要求支持区间加,单点查,还是树状数组即可。这部分的复杂度由 O(nlogn) 优化到 O(log2n)了。

Accepted

巨丑无比的代码:link。为了快速用了一个树状数组和一个线段树,主要内容在 main 函数中。

posted @   Little09  阅读(85)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示