[关闭]
@xiaoziyao 2021-07-07T03:11:35.000000Z 字数 2740 阅读 765

min25筛学习笔记

数学 学习笔记


前言

线性筛以的复杂度完成了数论函数的值域内求值,可是若要以更低的复杂度解决前缀求值,就要考虑更优的筛法了,例如杜教筛,Powerful Number,可是这两个筛法对函数都有较高的要求,于是我们要掌握更普适的筛子——min25筛。

min25筛可以以(一说,最新版本好像是)质数幂次上值为一个多项式的积性函数的前缀和。

模板

模板题:P5325 【模板】Min_25筛

题意:给定一个积性函数,满足,求

定义的最小质因子,为第个素数。

实际上,min25筛解决的问题可以解决是阶为常数的任意多项式的情况,本题只是一种特殊情况。

我们考虑对质数和合数分开考虑,后面的合数枚举其最小质因子及其幂次:

前面枚举到是因为任意合数的一定小于等于,后面那个是为了不算入而算入

考虑对于每个单项式,设其幂次为,设函数在素数上拟合,即

考虑怎么从转移过来,不难发现,否则要减去的贡献,而这个贡献容斥一下就是(考虑提出质因子,然后减去中多算的素数),即:

根据上面的素数合数分开算的式子,设

本题Powerful Number写法是的,但由于常数原因,我的min25比我的Powerful Number快一倍以上。

  1. #include<stdio.h>
  2. #include<math.h>
  3. const int maxt=100005,mod=1000000007,inv2=(mod+1)/2,inv6=(mod+1)/6;
  4. int t,cnt,tot;
  5. long long n;
  6. int sum1[maxt],sum2[maxt],p[maxt],c[maxt],id[maxt][2],g1[maxt<<1],g2[maxt<<1];
  7. long long val[maxt<<1];
  8. inline int add(int a,int b){
  9. return a+b>=mod? a+b-mod:a+b;
  10. }
  11. int S(long long v,int k){
  12. if(p[k]>=v)
  13. return 0;
  14. int w=id[v<=t? v:(n/v)][v>t],res=add(add(g2[w],mod-sum2[k]),mod-add(g1[w],mod-sum1[k]));
  15. for(int i=k+1;i<=cnt&&1ll*p[i]*p[i]<=v;i++)
  16. for(long long j=1,mul=p[i];mul<=v;j++,mul*=p[i])
  17. res=add(res,1ll*mul%mod*((mul-1)%mod)%mod*(S(v/mul,i)+(j>1))%mod);
  18. return res;
  19. }
  20. int main(){
  21. scanf("%lld",&n),t=sqrt(n),c[1]=1;
  22. for(int i=2;i<=t;i++){
  23. if(c[i]==0)
  24. p[++cnt]=i,sum1[cnt]=add(sum1[cnt-1],i),sum2[cnt]=add(sum2[cnt-1],1ll*i*i%mod);
  25. for(int j=1;j<=cnt&&i*p[j]<=t;j++){
  26. c[i*p[j]]=1;
  27. if(i%p[j]==0)
  28. break;
  29. }
  30. }
  31. for(long long L=1,R;L<=n;L=R+1){
  32. long long v=n/L;
  33. int w=v%mod;
  34. R=n/v,val[++tot]=v,id[v<=t? v:R][v>t]=tot;
  35. g1[tot]=add(1ll*w*(w+1)%mod*inv2%mod,mod-1),g2[tot]=add(1ll*w*(w+1)%mod*(w+w+1)%mod*inv6%mod,mod-1);
  36. }
  37. for(int i=1;i<=cnt;i++)
  38. for(int j=1;j<=tot&&1ll*p[i]*p[i]<=val[j];j++){
  39. long long v=val[j]/p[i];
  40. int w=id[v<=t? v:(n/v)][v>t];
  41. g1[j]=add(g1[j],mod-1ll*p[i]*add(g1[w],mod-sum1[i-1])%mod);
  42. g2[j]=add(g2[j],mod-1ll*p[i]*p[i]%mod*add(g2[w],mod-sum2[i-1])%mod);
  43. }
  44. printf("%d\n",add(S(n,0),1));
  45. return 0;
  46. }

P5493 质数前缀统计

SP34096 DIVCNTK - Counting Divisors (general)

1847 奇怪的数学题

#6682. 梦中的数论

#6235. 区间素数个数

#6053. 简单的函数

积性函数求和问题的一种筛法

参考资料:Min_25筛 学习小记

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注