\(Min\_25\)筛学习笔记

这种神仙东西不写点东西一下就忘了QAQ

资料和代码出处

资料2

资料3

打死我也不承认参考了yyb的

\(Min\_25\)筛可以干嘛?下文中未特殊说明\(P\)均指质数集合,\(p_i\)或\(p\)指某个具体质数。

求一类积性函数\(f(x)\)的前缀和,需要满足\(f(p)\)可以写成多项式的形式,或者操作一下可以写成多项式(如例题),且\(f(p^k)\)能快速求出。

讲真学这个东西比我什么都不会的时候学\(FFT\)都累。

Round 1

先求质数的贡献。我们要求

\[\sum_{i=1}^x[i是质数]f(i)$$。

我们可以设

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

注意到当\(p_j^2>x\)时,\(g(n,j)=g(n,j-1)\)因为没有新的贡献了,所以我们只要筛到\(\sqrt n\)的质数就可以了,这也是降低复杂度的关键。

我们还注意到\(g(n,|P|)=\sum_{i=1}^x[i是质数]f(i)\),\(|P|\)是\(\sqrt n\)内的质数集合大小。

关于\(g(n,j)\)的转移,我们有:

\[g(n,j)=g(n,j-1)-f(P_j)[g(\frac{n}{P_j},j-1)-\sum_{i=1}^{j-1}f(P_i)],P_j^2\le n
\]

意思大概就是减掉所有最小质因子为\(p_j\)的贡献,但由于\(g(\frac n{p_j},j-1)\)里包含了质数,而\(<p_j\)的质数是不能算的,所以要减掉。

由于我们只需要\(g(n,|P|)\),所以下面的代码是一维的,用递推实现。注意到过程中我们只需要\(g(\lfloor\frac ni\rfloor,|P|)\),所以最多只有\(2\sqrt n\)种取值

至于实现,由于我参考了\(gsy\)的实现,痛不欲生,于是决定把他的代码蒯走。这份代码是筛\(f(p)=1\)的。

//这两个鬼id就是你在杜教筛中碰到的卡常卡空间技巧,这份代码你理解了这个就能看懂
//至于YL,是机房众人mo的巨佬,所以是模数
//Sq是根号n
for (int i=1,j;i<=n;i=j+1)
{
j=n/(n/i);w[++m]=n/i;g[m]=(w[m]-1)%YL;//除法分块,根号n求出所有有用的值
if(w[m]<=sq)id1[w[m]]=m;else id2[n/w[m]]=m;
}
for (int j=1;j<=tot;++j)
for (int i=1;i<=m&&pri[j]*pri[j]<=w[i];++i)//i再往上就是所有的质数,会被后面抵消
{
int k=(w[i]/pri[j]<=sq)?id1[w[i]/pri[j]]:id2[n/(w[i]/pri[j])];
g[i]=(g[i]-g[k]+(j-1))%YL;g[i]=(g[i]+YL)%YL;
}

Round 2

然而敌人并没有这么容易就被打倒,我们还有合数没算呢。那么我们鼓捣一个\(S(n,i)\)出来

\[S(n,j)=\sum_{i=1}^n[\min(p)\ge P_j]f(i)
\]

注意\(S(n,1)\)没算到\(f(1)\)。答案就是\(S(n,1)+f(1)\)。

递推式来了

\[S(n,j)=(质数的贡献)+(合数的贡献)
\]

有没有感觉被骗了\(QwQ\),我们继续

\[(质数的贡献)=g(n,|P|)-\sum_{i=1}^{j-1}f(P_i)
\]

\[(合数的贡献)=\sum_{k=j}^{P_k^2\le n}\sum_{e=1}^{P_k^{e+1}\le n}S(\frac{n}{P_k^e},k+1)\times f(P_k^e)+f(P_k^{e+1})
\]

经过\(YL\)的指点,我可以口胡一下了,每个合数要在最小质因子处被筛到。当\(\frac n{p_k^e}<p_{k+1}\)时,肯定是\(0\)就没必要继续了。

举个栗子,形如\(t*p_k^3\)(其中\(t\)的最小质因子大于\(p_k\))的数会被\(S(\frac n{p_k^3},4)\)包含。

由于\(S\)这个函数在任何时候都不包含\(f(1)\)所以我们要手动加上\(f(p_k^2),f(p_k^3),...,f(p_k^{e+1})\)其中\(p_k^{e+2}>n\)。什么,你问我\(f(p_k)\)去哪了,这不是个质数么。

完结撒花

放上LOJ6053简单的函数作为例题,这里面的\(p\)^\(c\)对于质数来说除了\(2\)以外都是\(p-1\),像个多项式。

代码中\(g(x,|P|)=\sum_{i=1}^x[i是质数]i\),\(h(x,|P|)=\sum_{i=1}^x[i是质数]1\)

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define gt getchar()
#define ll long long
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
inline ll in()
{
ll k=0;char ch=gt;
while(ch<'-')ch=gt;
while(ch>'-')k=k*10+ch-'0',ch=gt;
return k;
}
const int N=1e6+5,YL=1e9+7,mod=YL;
inline int MO(const int &x){return x>=YL?x-YL:x;}
ll n,w[N];
int np[N],pr[N],tot,h[N],g[N],sp[N],id1[N],id2[N],m,sq;
void seive(int n)
{
for(int i=2;i<=n;++i)
{
if(!np[i])pr[++tot]=i,sp[tot]=MO(sp[tot-1]+i);
for(int j=1;i*pr[j]<=n;++j)
{np[i*pr[j]]=1;if(i%pr[j]==0)break;}
}
} int S(ll x,int y)
{
if(x<=1||pr[y]>x)return 0;
int k=(x<=sq?id1[x]:id2[n/x]);
int res=MO(((ll)g[k]-h[k]-sp[y-1]+y-1)%YL+YL);
if(y==1)res+=2;
for(int i=y;i<=tot&&1ll*pr[i]*pr[i]<=x;++i)
{
ll p1=pr[i],p2=p1*pr[i];
for(int e=1;p2<=x;++e,p1=p2,p2*=pr[i])
res=MO(res+(1ll*S(x/p1,i+1)*(pr[i]^e)+(pr[i]^e+1))%YL);
}
return res;
} int main()
{
n=in();sq=sqrt(n);seive(sq);ll t;
for(ll i=1,j;i<=n;i=j+1)
{
j=n/(n/i),w[++m]=n/i;
if(w[m]<=sq)id1[w[m]]=m;else id2[n/w[m]]=m;
h[m]=(w[m]-1)%YL;g[m]=((w[m]+2)%YL)*((w[m]-1)%YL)%YL;
if(g[m]&1)g[m]+=YL;g[m]>>=1;
} for(int j=1;j<=tot;++j)
for(int i=1;i<=m&&1ll*pr[j]*pr[j]<=w[i];++i)
{
t=w[i]/pr[j];int k=(t<=sq?id1[t]:id2[n/t]);
h[i]=MO((h[i]-h[k]+j-1)%YL+YL);
g[i]=MO(MO(g[i]-1ll*pr[j]*(g[k]-sp[j-1])%YL)+YL);
}
printf("%d\n",S(n,1)+1);
return 0;
}

一些也许是高阶的应用?

筛与最小质因子有关的东西,用第一步筛,筛的时候顺便处理一下。

筛最大次大质因子有关,考虑后面的筛,其中在乱搞一下就行了。

主要要深刻的理解min_25筛的过程,本质上是容斥?(我口胡的

多做题就明白了。

我偷偷的把YCB的题单蒯过来。

泥萌看着办吧。

随机推荐

  1. Luogu4921/4931 情侣?给我烧了! 组合、递推

    4921 4931 第一眼看着就像容斥,但是容斥不怎么好做-- 第二眼想到错排,结果错排公式糊上去错了-- 不难考虑到可以先选\(K\)对情侣坐在一起,剩下\(N-K\)对错排 选\(K\)对情侣坐在 ...

  2. SPOJ1557 GSS2 Can you answer these queries II 历史最值线段树

    传送门 题意:给出一个长度为$N$的数列,$Q$次询问,每一次询问$[l,r]$之间的最大子段和,相同的数只计算一次.所有数字的绝对值$\leq 10^5$ GSS系列中不板子的大火题,单独拿出来写 ...

  3. 【iOS】build diff: /../Podfile.lock: No such file or directory

    Github 上下载的开源项目,在 Xcode 打开运行后报了错,如图所示: 解决方法: 在工程设置中的 Build Phases 下删除 Check Pods Manifest.lock 及 Cop ...

  4. VS2017中 C# dll引用(C生成dll,C++生成dll)小结 - 简书

    原文:VS2017中 C# dll引用(C生成dll,C++生成dll)小结 - 简书 dll引用小结 一.dll与应用程序 动态链接库(也称为DLL,即为“Dynamic Link Library” ...

  5. ORA-00020:maximum number of processes (150) exceeded

    异常的含义 超过最大的进程数 我们使用下面的语句可以查看与进程(process)的相关参数: 如上所示,这里的最大进程数是150. 问题可能存在的原因 1.应用程序在使用数据库连接池时,使用完成后没有 ...

  6. [Spark][python]RDD的collect 作用是什么?

    [Spark][Python]sortByKey 例子的继续 RDD的collect() 作用是什么? “[Spark][Python]sortByKey 例子”的继续 In [20]: mydata ...

  7. 【知识整理】这可能是最好的RxJava 2.x 入门教程(一)

    一.前言 这可能是最好的RxJava 2.x入门教程系列专栏 文章链接: 这可能是最好的RxJava 2.x 入门教程(完结版)[强力推荐] 这可能是最好的RxJava 2.x 入门教程(一) 这可能 ...

  8. React.js 入门与实战课程思维导图

    原文发表于我的技术博客 我在慕课网的「React.js 入门与实战之开发适配PC端及移动端新闻头条平台」课程已经上线了,在这里分享了课程中的思维导图,供大家参考. 原文发表于我的技术博客 此导图为课程 ...

  9. Lucene源码

    看Lucene源码必须知道的基本概念 终于有时间总结点Lucene,虽然是大周末的,已经感觉是对自己的奖励,毕竟只是喜欢,现在的工作中用不到的.自己看源码比较快,看英文原著的技术书也很快.都和语言有很 ...

  10. .NET 使用 RabbitMQ 图文简介

    前言 最近项目要使用RabbitMQ,园里里面已经有很多优秀的文章,Rabbitmq官网也有.net实例.这里我尝试下图文并茂之形式记录下使用的过程. 安装 RabbitMQ是建立在erlang OT ...