min_25筛

min_25筛

用来干啥?

考虑一个积性函数F(x),用来快速计算前缀和i=1nF(i)

当然,这个积性函数要满足F(x),xPrime可以用多项式表示

同时,F(xk),xPrime要能够快速计算答案

需要预处理的东西

先不考虑求前缀和的问题,考虑一个积性函数F(x)

求解i=1n[iPrime]F(i)

直接求我也会懵逼的,还是找一个函数来算算,假设F(x)=xk

那么,求解i=1n[iPrime]ik

P是质数集合,Pi表示第i个质数。

设$$g(n,j)=\sum_{i=1}nik[i\in P\ or \ min(p)>P_j,p|i,p\in P\ ]$$

你问我为什么不写中文?因为LaTex里面写中文太丑了

翻译成人话,i是质数,或者i的最小质因子大于Pj

我们考虑一下g(n,j)这个函数可以怎么转移。

考虑第一种情况,如果Pj2>n,很明显,最小质因子是Pj的最小合数就是Pj2

如果Pj2>n,显然不会产生新的贡献了,此时有g(n,j)=g(n,j1)

那么,如果Pj2n呢?

显然,从Pj1Pj,我们能够产生贡献的值变少了,因此我们要减去一些东西的值。

所以g(n,j)=g(n,j1)X,考虑一下X是啥。

我们减去的贡献显然就是哪些最小质因子是Pj的东西,所以前面有一个Pjk的系数,

后面有还有一些东西。

现在因为所有数都分成了两个部分,一个是已经被提出来的Pj,另外一部分是剩余的数。

考虑剩余的数的最小质因数,我们要减去的就是那些最小质因数仍然大于等于Pj的那部分

所以容斥一下,先算上所有的含有Pj这部分的贡献g(nPj,j1)

再减掉其他质数以及最小质因数小于Pj的那部分,也就是g(Pj1,j1)

所以我们推出转移

g(n,j)=g(n,j1)Pjk[g(nPj,j1)g(Pj1,j1)]

把两个转移合并一下,就是

g(n,j)={g(n,j1)Pj2>ng(n,j1)Pjk[g(nPj,j1)g(Pj1,j1)]Pj2n

考虑一下g(Pj,j)的值?显然是$$\sum_{i=1}jP_jk$$

我们要求的是什么?g(n,|P|),其中|P|Prime集合的大小,也就是满足条件的质数的个数。

而我们根据上面的转移,发现需要的质数只有不大于n的,所以只需要筛出这些质数就好了。

我们来思考一下g函数所代表的含义,

我们可以理解为在模拟埃氏筛法的过程,

g(n,j)表示[1,n]排成一列放在这里,但是你已经晒过一些质数了,

你把前j个质数的倍数全部划掉了,剩下的求个F(x)的和就是g函数。

所以转移的过程可以理解为已经筛完了前j1个质数,现在考虑删除第j个质数的过程。

看到这里一定会感觉上面十分的有道理,但是又有一些疑问。

在上面的计算过程中,始终只考虑了n的质数,那么,那些>n的质数呢?

其实,我们的g函数要计算的本来就只有质数的值,所以,我们的g函数算出来的结果并不是真正的结果。

还记得上面对于这类积性函数有什么要求吗?能够快速的计算F(x),xPrime

所以,我们先假设所有的数的计算方法都等同于质数的计算方法,所以我们可以快速的计算前缀和

也就是g(n,0),虽然这个值是假的。但是,如果g中只包含了质数的值的话,那么它的计算结果就是真正的结果。

因此,预处理g的过程,我们理解为一个计算所有质数的值的过程。

怎么算我们要的东西呢?

接着我们来考虑求积性函数的前缀和。

S(n,j)=i=1nF(i)[min(p)Pj,pP,p|i ]

后面的意思和上面是一样的,也就是所有最小质因数大于PjiF(i)之和

那么,S(n,j)分为两个部分计算,一部分是所有质数的和,一部分是所有合数的和,1的值单独算一下。

所有质数的值显然可以用g表示出来,也就是g(n,|P|),当然,这里还需要考虑一下质数大小的限制

考虑合数部分的贡献。

枚举一下每个合数的最小质因子以及最小质因子的次幂,这样可以进行转移。

S(n,j)=g(n,|P|)i=1j1f(Pi)+kje(F(Pke)S(nPke,k+1)+F(Pke+1))

为什么?

因为F(x)是一个积性函数,所以我们把它的最小质因数拆出来,考虑剩下部分然后再乘起来是没有问题的。

所以我们枚举他的最小质因数,然后只需要考虑除完之后剩下部分的答案就好了。

因为最小质因数已经被除完,所以剩下部分中不能再含有最小质因数。

同时,所有的F(pki)也被筛掉了,所以需要额外的补进来。

一个栗子

LOJ#6053 简单的函数

积性函数为f(pc)=pc,pPrime

我们来考虑质数的贡献,因为除2外的所有质数都是奇数,所以f(p)=p1

f(2)=p+1=2+1=3

我们先把所有的数的贡献都当做p来算,这样可以方便我们计算g的值。

再注意到一点,我们真正在计算g(n,j)的时候,并不需要计算出所有的n

我们发现每次转移的时候只与整除有关,所以考虑一下数论分块后的结果,

这样的值大约只有2n个,所以只需要这些数的值。我们可以预处理出来,然后存起来。

初值计算g(n,0)=i=2nf(i)

当然这里的f(i)是“假的”f(i),也就是我们把所有的数都当成质数来计算

也就是f(i)=i,所以求和的结果是n(n+1)21

然后我们看到上面的式子,还需要维护一下筛出来的质数的前缀f(x)和,也就是g(Pi1,i)

这个的话我们在筛质数的时候直接维护一下就好了。

因为对于所有的质数,我们实际的f(i)i1,所以还需要维护一下质数的个数,

也就相当于维护一个积性函数h(x)=1,和前面g函数一样的计算就行了。

接下来就表示成h(n,j)了。

然后如何计算答案?

我们采用递归的方法,并且不需要记忆化

先考虑一下S(n,j)的初值,也就是所有满足条件的质数的答案

这个答案是g(n,|P|)i=1j1(Pi1)h(n,|P|)

为啥?首先是所有质数的f(x)的值,就是前面的g函数

然后因为最小的质数是Pj,所以把小于Pj的质数的贡献给减掉

然后因为要计算的f(x)x1,所以还需要额外减那个1,也就是质数的个数。

如果j=1的时候,f(2)=3,但是在计算过程中我们算的是f(2)=1,所以需要额外的加二

这样一来就差不多可以实现了。
代码戳这里

posted @   小蒟蒻yyb  阅读(15817)  评论(10编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示