2021杭电多校10 D.Pty hates prime numbers题解,容斥
前言
暑期第三次组队赛是选的21年杭电多校10,遗憾爆0,被对面队打爆,赛后狠狠补题。这道题的题解,以及网上搜到的其他题解看了好久没看懂,在问了队里大腿多次后,总算磨出来了,这里讲一下我的理解。
题意
多次询问,每次给定 和 , 如果一个数的质因数里包括前 个质数,则这个数是 讨厌 的,问 到 中有多少个数是不讨厌的。
数据范围
思路
首先直接 的枚举质因数,然后容斥,这个是简单的。具体来说就是直接dfs 爆搜,枚举每个质因数选或者不选,选的话就乘上这个数,最终得到一个 以及 容斥系数 ,容斥系数根据选的质因数的奇偶性,决定是 或者 。然后将答案加上 中是 的倍数的个数乘 。
通过这个容斥, 我们能得到的是 1 - n 中不是前k个质数倍数的个数 ,这句话,以及题解里面也是类似的描述,有一点歧义的地方。不是前k个质数的倍数,意思是质因数不包含前 k 个质数。而不是,不是前k个质数的乘积的倍数(因为题解里面多次强调了前8个质数的乘积9699690,就容易误解不是前8个质数倍数,指不是9699690倍数)。
然后因为 的数据范围是16,所以直接这样 容斥枚举是T的,因为多测次数很多。所以正解的思路是,先对前8个质数进行容斥枚举,预处理出一个数组 表示 到 中,质因数不包含前8个质数的数字个数。然后只对第 到第 个质数进行枚举容斥。
就是这个什么叫只对后面几个数进行容斥,把我控了很久,因为普通的容斥,肯定是考虑前面和后面,总的选的数的个数,决定正负啥的。
然后我是这样去理解:
对一些位去容斥,最终目的是为了求出,1 - n 中不包含这些质因数的数字个数。然后我们对 9 到 k位去容斥,所以保证了这些数一定不包含9 到 k个质因数,然后我们只需要再保证这些数不包含前8个质因数,那这些数就是符合题意的。换言之,就是在容斥后几位的同时,保证能忽略掉前8位的影响。
然后具体的,由于容斥过程中,我们枚举了哪些质因数得到乘积 之后,我们要求的反而是 中是 的倍数的个数。
因为是对后几个质因数容斥,所以我们要求的是 中是枚举到的后几个质因数的倍数的个数,因为忽略了前8位,所以我们还得保证求出来的这些数不能有前 8个质因数 。也就是,通过容斥计算 不含后几位质因数的数量,在整个容斥过程中,还保证了全程枚举到的数不包含前 个质因数,所以最终算出来的就是前 个质因数都不包含的总数。
在后几位的容斥过程中,假如枚举到的乘积是 ,问题转化为求 中是 的倍数,并且不包含前 个质因数的数字个数。
由于是 倍数,所以这些数 一定能表示成 ,因为 是后几个质因数倍数,所以肯定不含前 个质因子。所以我们相当于,求 中,有多少个数不含前 个质因数,这个问题等价于求 的子问题了。所以可以预处理 的所有答案。
然后由于 很大,没办法预处理 的所有答案,这时候还需要发现一个性质。 由于前8个质因数的乘积,或者说是最小公倍数是9699690, 假设有一个比较大的 , 画在数轴上,把有前 个质因数的点 标1,那么显然这些数的 就是一个循环节,所以 这个很大的 的答案等于拥有这些循环节的个数乘上一个循环节的答案,加上多出来那一截 对应的答案。(从这个循环节和数轴的角度,感觉比较好理解题解里面那个为什么要取余 lcm)
所以得到题解里面那个式子,这里的答案指的是 时, 中不含前 个质因数的数字个数。
然后就是代码了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现