Min_25筛学习笔记

由于Min_25筛过于难学于是又来记笔记了
Min_25筛用于求解次数比较小的多项式积性函数的前缀和。
拿洛谷例题为例:
定义积性函数\(f(x)\),且\(f(p^k)=p^k(p^k-1)\),求\(\sum\limits_{i=1}^nf(i)\)
由于次数比较低我们分次数考虑,下面过程都是在同一次数下进行。
首先按照质数和非质数分类:

\[\sum\limits_{i=1}^{n}f(i)=\sum\limits_{p<=n}f(p)+\sum\limits_{1<=p^e<=n,1<=p<=\sqrt{n}}f(p^e)(\sum\limits_{1<=i<=n/p^e\&\&minp_i>p}f(i)) \]

其中\(minp_i\)表示i的最小质因子。
先看第一部分。
\(g_k(n,j)=\sum\limits_{i=1}^{n}[i\ is\ a\ prime \ or\ minp>p_j]i^k\)
注意\(i^k\)只在质数处和f取值相同,也就是\(i^k\)是我们构造的一个完全积性函数。
然后考虑\(g(n,i)\)\(g(n,i-1)\)转移过来,有:

\[g(n,i)=g(n,i-1)-p_i^k(g(n/p_i,i-1)-g(p_{i-1},i-1)) \]

也就是去掉不符合条件的合数,这些合数肯定都是最小质因子等于\(p_i\)的,然后去掉g中包含的质数。
然后注意到后面一项中\(g(p_{i-1},i-1)\)就是前\(j-1\)个质数的k次方和,由于\(p_i<=\sqrt{n}\)所以可以线性筛预处理,设为\(sp_x\)。那么[1,n]中所有质数的k次方和其实就是\(g(n,x)\)\(p_x\)是最后一个小于等于\(\sqrt{n}\)的质数,记做\(g(n)\).
但是n还是太大了。但是我们又发现 \(\left\lfloor\frac{n}{x}\right\rfloor\)只有\(\sqrt{n}\)级别,可以离散化记录一下分别是谁然后求解,这样的话对每个处于此之内的根号以下的质数都有1次求解,复杂度就是\(\sum\limits_{\left\lfloor\frac{n}{x}\right\rfloor}\sum\limits_{i=1}^{\sqrt{ \left\lfloor\frac{n}{x}\right\rfloor}}[i\ is\ a\ prime]\)

然后求解答案。设\(f(n,x)\)表示\([1,n]\)中最小质因子大于\(p_x\)的数的f之和,答案就是\(S(n,0)\)
把它分成两部分,一部分是大于\(p_x\)的质数,也就是\(g(n)-sp_x\),剩下的枚举最小质因子:

\[S(n,x)=g(n)-sp_x+\sum\limits_{p_k^e<=n\&\&k>x}f(p_k^e)(S(\frac{n}{p_k^e},k)+[e!=1]) \]

然后递归求解即可。

然后放个码:

#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;
	#define pf printf
	#define F(i,a,b) for(int i=a;i<=b;i++)
	#define D(i,a,b) for(int i=a;i>=b;i--)
	inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=2e5+10,mod=1e9+7,inv3=(mod+1)/3;
	int sq,sp1[N],sp2[N],g1[N],g2[N],prime[N],co,id1[N],id2[N];bool vis[N];
	ll w[N],n;
	inline void init(int n){
		F(i,2,n){
			if(!vis[i])prime[++co]=i,sp1[co]=sp1[co-1]+i,sp1[co]-=sp1[co]>=mod?mod:0,sp2[co]=(1ll*i*i+sp2[co-1])%mod;
			F(j,1,co){
				if(prime[j]*i>n)break;
				vis[prime[j]*i]=1;
				if(i%prime[j]==0)break;
			}
		}
	}
	inline int S(ll x,int y){
		if(prime[y]>=x)return 0;
		int k=x<=sq?id1[x]:id2[n/x];
		int ans=(0ll+g2[k]-g1[k]+mod+sp1[y]-sp2[y]+mod)%mod;
		F(i,y+1,co){
			if(1ll*prime[i]*prime[i]>x)break;
			int e=1;
			for(ll p=prime[i];p<=x;e++,p*=prime[i]){
				int v=p%mod;
				ans+=1ll*v*(v+mod-1)%mod*(S(x/p,i)+(e!=1))%mod;
				ans-=ans>=mod?mod:0;
			}
		}return ans;
	}
	inline short main(){
		n=read(),sq=sqrt(n),init(sq);
		for(ll l=1,r;l<=n;l=r+1){
			r=n/(n/l),w[++w[0]]=n/l,g1[w[0]]=w[w[0]]%mod,
			g2[w[0]]=1ll*g1[w[0]]*(g1[w[0]]+1)/2%mod*(2ll*g1[w[0]]+1)%mod*inv3%mod-1;
			g1[w[0]]=1ll*g1[w[0]]*(g1[w[0]]+1)/2%mod-1;
			if(n/l<=sq)id1[n/l]=w[0];else id2[r]=w[0];
		}
		F(i,1,co){
			F(j,1,w[0]){
				if(1ll*prime[i]*prime[i]>w[j])break;
				int k=w[j]/prime[i]<=sq?id1[w[j]/prime[i]]:id2[n/(w[j]/prime[i])];
				g1[j]-=1ll*prime[i]*(g1[k]-sp1[i-1]+mod)%mod;
				g2[j]-=1ll*prime[i]*prime[i]%mod*(g2[k]-sp2[i-1]+mod)%mod;
				g1[j]+=g1[j]<0?mod:0,g2[j]+=g2[j]<0?mod:0;
			}
		}pi(S(n,0)+1);
		return 0;
	}
}
signed main(){return EMT::main();}

然后下午刷了几道题

简单的函数

求出来每个质数的前缀和其实就好做了。发现\(f(i)\)当i不是2且i是质数时就是\(i-1\)于是分别求解\(f(i)=i\)\(f(i)=1\),然后减一下,把2的值补上就完事了。

Sanrd

仔细观察可以发现我们无法发现积性函数。
但是我们还是可以套用Min_25筛的过程。设\(S(n,i)\)表示\(<=n\)的数中\(minp>p_i\)的f值之和,还发现质数和1没有贡献,于是直接就有:

\[S(n,i)=\sum\limits_{p^e_k<=\sqrt{x}\&\&k>i}S(n/p_k^e,i)+p_k\times (g(\frac{n}{p_k^e})-(i-1)) \]

就是枚举这个质数的贡献。其中\(g_i\)表示\(i\)以内质数个数,还是可以通过dp求出。

\[g(n,i)=g(n,i-1)-(g(n/p_i,i-1)-g(p_i-1,i-1)) \]

然后直接就是\(S(r,0)-S(l-1,0)\)

Misaka Network 与求和

简单化一下式子就变成了:

\[ans=\sum\limits_{T=1}^{n}(\frac{n}{T})^2(f*\mu)(i) \]

然后我们发现\((f*\mu)*1=f*(\mu*1)=f\)
于是设\(g(n)=\sum\limits_{i=1}^n(f*\mu)(i)\)
就有:

\[\sum\limits_{i=1}^nf(n)=\sum\limits_{i=1}^{n}g(\frac{n}{i}) \]

\[g(n)=\sum\limits_{i=1}^nf_i-\sum\limits_{i=2}^ng(\frac{n}{i}) \]

然后f可以min25筛然后杜教筛再整除分块一下即可。

posted @ 2022-01-16 10:52  letitdown  阅读(80)  评论(2编辑  收藏  举报