min_25筛学习笔记

参考博客

zsy

xuyixuan

litble

前置

min25min_25就是一种能在低于线性复杂度求积性函数f(x)f(x)前缀和的筛法

复杂度大概为O(n34logn)O(\frac{n^{\frac 3 4}}{log_n})(不会证,不过朱老大论文里有证明(看不懂))

要求f(x)f(x)是一个积性函数,而且对于素数ppf(p)f(p)f(pk)f(p^k)可以快速得到

gg

PP表示素数集合,MinkMin_k表示kk的最小质因子

pripr_i表示从小到大第ii个素数

首先考虑求出i=1n[iP]f(i)\sum_{i=1}^{n}[i\in P] f(i)

定义g(n,i)=j=1n[jPorMinj>pri]f(i)g(n,i)=\sum_{j=1}^{n}[j\in P{or}Min_j>pr_i] f(i)

仔细瞪一下这个函数

我们发现从g(n,i1)g(n,i-1)g(n,i)g(n,i)

我们就相当于做埃氏筛的过程,用pripr_i[1,n][1,n]所有还没有被筛去的pripr_i的倍数筛去

实际上g(n,i)g(n,i)就是对[1,n][1,n]用前ii个素数做一次埃氏筛后剩下的数ff之和

现在考虑怎么从g(n,i1)g(n,i-1)推到g(n,i)g(n,i)

首先如果pri2>npr_{i}^2> n那显然不会有筛去任何数

否则考虑哪些数被删去了

一定是含质因子pip_i,而且除去pip_i后最小质因子一定大于pip_i

考虑其实也就是减去f(pi)×g(npi,i1)f(p_i)\times g(\frac n {p_i},i-1)

又由于我们把pr1pr_1~pri1pr_{i-1}这些素数的ff值减去了,所以要再加一个j=1i1f(pj)\sum_{j=1}^{i-1}f(p_j)

所以
g(n,i)={g(n,i1)n<pi2g(n,i1)f(pi)×[g(npi,i1)j=1i1f(pj)]pi2ng(n,i)=ni=0 g(n,i)= \begin{cases} g(n,i-1) && n<p_i^2\\ g(n,i-1)-f(p_i)\times[g(\frac n{p_i},i-1)-\sum_{j=1}^{i-1}f(p_j)] && p_i^2\le n\\ g(n,i)=n && i=0 \end{cases}

由于最后实际要求的是g(n,P)g(n,|P|),我们只需要开一维就可以了,第二维可以类似滚动数组滚掉

又由于大于n\sqrt n的质因子只有一个

所以我们可以记f1[i]f1[i]表示g(i,j)g(i,j)f2[i]f2[i]表示g(ni,j)g(\frac n i,j)

这样空间复杂度只有O(n)O(\sqrt n)

代码:当f(p)=1f(p)=1即求素数个数时
代码实现比较精细
可以证明这样复杂度是O(n34logn)O(\frac{n^{\frac 3 4}}{log_n})

int lim=sqrt(n);
for(int i=1;i<=lim;i++)f1[i]=i-1,f2[i]=n/i-1;
for(int p=2;p<=lim;p++){
	if(f1[p]==f1[p-1])continue;
	for(int i=1;i<=lim/p;i++)f2[i]-=f2[i*p]-f1[p-1];
	for(int i=lim/p+1;1ll*i*p*p<=n&&i<=lim;i++)f2[i]-=f1[n/i/p]-f1[p-1];
	for(int i=lim;i>=1ll*p*p;i--)f1[i]-=f1[i/p]-f1[p-1];
}
return f2[1];

但是会跑的很慢
你找一照发现问题很简单
卡一下数组枚举和除法以及一些常用变量就会快565、6

lim=sqrt(n);
for(i=1;i<=lim;++i)f1[i]=i-1,f2[i]=n/i-1,inv[i]=1.0/i;
for(p=2;p<=lim;++p){
	if(f1[p]==f1[p-1])continue;
	x0=f1[p-1],w1=lim/p,w2=min(lim,(n/p/p)),dd=n/p;
	for(i=1;i<=w1;++i)f2[i]+=x0-f2[i*p];
	for(i=lim/p+1;i<=w2;++i)f2[i]+=x0-f1[(int)(inv[i]*dd+1e-7)];
	for(i=lim;i>=1ll*p*p;--i)f1[i]+=x0-f1[(int)(inv[p]*i+1e-7)];
}
return f2[1];

SS

现在我们已经求出了i=1n[iP]f(i)\sum_{i=1}^{n}[i\in P] f(i)

考虑如何计算合数的答案

S(n,i)=j=1n[Minjpri]f(j)S(n,i)=\sum_{j=1}^n [Min_j\geq pr_i] f(j)

即满足所有质因子大于等于pip_i的数的ff之和

那么显然i=1nf(i)=S(n,1)+f(1)\sum_{i=1}^{n} f(i)=S(n,1)+f(1)
考虑如何类似的递推

首先素数的答案已经算出来了
显然的是g(n,P)j=1i1f(prj)g(n,|P|)-\sum_{j=1}^{i-1}f(pr_j)(因为SS要求MinjpriMin_j\ge pr_i)

考虑枚举合数的最小质因子和次数,直接算就是了

S(n,i)=g(n,P)j=1i1f(prj)+j=iprj2nxs=1prjxs+1nS(nprjxs,j+1)×f(prjxs)+f(prjxs+1)S(n,i)=g(n,|P|)-\sum_{j=1}^{i-1}f(pr_j)+\sum_{j=i}^{pr_j^2\le n}\sum_{xs=1}^{pr_j^{xs+1}\le n}S(\frac{n}{pr_j^{xs}},j+1)\times f(pr_j^{xs})+f(pr_j^{xs+1})

好像这样的复杂度是n1ϵlogn\frac{n^{1-\epsilon}}{logn}
不过跑的还比较快

然后就没了
代码看例题里的就可以了

例题:

LOJ6235LOJ6235

LOJ6202LOJ6202

LOJ6053LOJ6053

UOJ188UOJ188

BZOJ5244BZOJ5244

SPOJDIVCNTKSPOJ-DIVCNTK

posted @ 2019-07-28 14:56  Stargazer_cykoi  阅读(132)  评论(0编辑  收藏  举报