Min_25筛学习笔记

0、一些定义

  • 定义域为正整数集,陪域为复数域的函数被称为数论函数
  • (f(x))是一个数论函数,若对于任意一对互质的正整数(a,b),有(f(ab)=f(a)f(b)),则称(f(x))积性函数
  • (delta(x))(x)的最小质因子,(gamma(x))(x)的最大质因子。
  • (cnt(x))(x)的质因子个数。
  • 记第(i)个质数为(p_i)。特别地,(p_0=1)
  • (pi(x))为不超过(x)的质数个数。由素数定理,(pi(x)=O(frac{x}{log x}))

1、min_25筛

论文题:定义(sigma_0(n))(n)的正约数个数,求(S(n)=sum_{i=1}^nsigma_0(i^k))(n,kleq 10^{10})

拓展:给定一个积性函数(f(x)),且对于任意质数(p)和正整数(e),满足:

  • (f(p))是一个关于(p)的低次多项式。
  • 计算(f(p^e))的复杂度可忽略。
  • (S(n)=sum_{i=1}^nf(i))

解法

(f(x)=sigma_0(x^k)),容易发现(f(x))是积性函数。

[g(n,i)=sum_{substack{2leq xleq n\ delta(x)> p_i}}f(x) ]

那么(S(n)=f(1)+g(n,0))

考虑计算(g(x))的递推式,将(x)分成质数和合数两个部分,合数部分枚举最小质因子(一定(leq sqrt{n})),质数部分单独计算,于是

[egin{align*} g(n,i)&=sum_{substack{i< jleq pi(sqrt{n})}} sum_{substack{2leq xleq n\ delta(x)=p_j}}f(x)+sum_{i< jleq pi(n)}f(p_j) \&=sum_{substack{i< jleq pi(sqrt{n})\ p_j^{e+1}leq n,egeq 1}} left(f(p_j^{e+1})+f(p_j^e)sum_{substack{2leq xleq leftlfloorfrac{n}{p_j^e} ight floor\ delta(x)> p_j}}f(x) ight)+sum_{i< jleq pi(n)}f(p_j) \&=sum_{substack{i< jleq pi(sqrt{n})\ p_j^{e+1}leq n,egeq 1}} left(f(p_j^{e+1})+f(p_j^e)gleft(leftlfloorfrac{n}{p_j^e} ight floor,j ight) ight)+sum_{1leq jleq pi(n)}f(p_j) -sum_{1leq jleq i}f(p_j)end{align*}]

[h(n)=sum_{1leq ileq pi(n)}f(p_i) ]

那么

[g(n,i)=sum_{substack{i< jleq pi(sqrt{n})\ p_j^{e+1}leq n,egeq 1}} left(f(p_j^{e+1})+f(p_j^e)gleft(leftlfloorfrac{n}{p_j^e} ight floor,j ight) ight)+h(n)-h(p_i) ]

如果能快速计算(h),就可以在很低的复杂度里递推求出(g(n,0))。注意到(f)在质数处的取值为多项式,所以只需要对于非负整数(s),计算(h_s(n)=sum_{1leq ileq pi(n)}p_i^s)。注意到(g(n,i))的递推过程,我们只需要对于(1,2,ldots,lfloorsqrt{n} floor,leftlfloorfrac{n}{lfloorsqrt{n} floor} ight floor,ldots,leftlfloorfrac{n}{2} ight floor,n)(O(sqrt{n}))个数求出(h)值。

(h_s'(n,i)),为前(n)个数,经过(i)次埃氏筛后剩下的数的(s)次幂之和。那么(h_s(n)=h_s'(n,pi(sqrt{n})))

对于计算(h_s'(n,i))的递推式,考虑第(i)轮埃氏筛的过程:

  • (n<p_i^2),那么不会有任何数被筛去,于是(h_s'(n,i)=h_s'(n,i-1))
  • (ngeq p_i^2),那么被筛去的数必有质因子(p_i),于是应当减去(p_i^sh_s'left(leftlfloorfrac{n}{p_i} ight floor,i-1 ight))。但是会有最小质因子小于(p_i)的数被减去,所以应当加上这部分的贡献,为(p_i^sh_s'(p_{i-1},i-1))

那么

[h_s'(n,i)=h_s'(n,i-1)-[ngeq p_i^2]p_i^sleft(h_s'left(leftlfloorfrac{n}{p_i} ight floor,i-1 ight)-h_s'(p_{i-1},i-1) ight) ]

边界条件为

[h_s'(n,0)=sum_{i=2}^ni^s ]

暴力实现即可。

时间复杂度

(O(frac{n^frac{3}{4}}{log n}))

证明咕着。

例题

【模板】Min_25筛

注意(f)在质数(p)上的取值为(p^2-p),于是需要同时求出质数的和和平方和,即(h_1,h_2)。然后照着公式实现即可。

#include<cstdio>
#define ll long long
#define P 1000000007
#define inv3 333333336
#define N 200005

ll n;

int prm[N],_prm;
bool vis[N];
inline void sieve(int x){
	for(int i=2;i<=x;i++){
		if(!vis[i])
			prm[++_prm]=i;
		for(int j=1;j<=_prm&&i*prm[j]<=x;j++){
			vis[i*prm[j]]=1;
			if(!(i%prm[j]))
				break;
		}
	}
}

int sq,m;
inline int id(ll x){
	return x<=sq?x:m-n/x+1;
}
ll num[N];
int h1[N],h2[N];//h(x)=h2(x)-h1(x),h1,h2开成滚动数组 
inline void get_h(){
	while(1ll*sq*sq<=n)
		sq++;
	sq--;
	sieve(sq);
	for(int i=1;i<=sq;i++)
		num[++m]=i;
	for(int i=sq;i;i--)
		if(n/i>sq)
			num[++m]=n/i;
	for(int i=1;i<=m;i++){
		int tmp=num[i]%P;
		h1[i]=1ll*tmp*(tmp+1)/2%P-1;
		h2[i]=1ll*tmp*(tmp+1)/2%P*(2*tmp+1)%P*inv3%P-1;
	}//边界条件 
	for(int i=1;i<=_prm;i++)
		for(int j=m;num[j]>=1ll*prm[i]*prm[i];j--){//注意倒序递推 
			int k=id(num[j]/prm[i]);
			h1[j]=(h1[j]-1ll*prm[i]*(h1[k]-h1[prm[i-1]]+P)%P+P)%P;
			h2[j]=(h2[j]-1ll*prm[i]*prm[i]%P*(h2[k]-h2[prm[i-1]]+P)%P+P)%P;
		}
}

inline int g(ll x,int i){
	int k=id(x),res=((h2[k]-h1[k]+P)%P-(h2[prm[i]]-h1[prm[i]]+P)%P+P)%P;//h(x)-h(p_i)
	for(int j=i+1;j<=_prm&&1ll*prm[j]*prm[j]<=x;j++)
		for(ll pe=prm[j];pe*prm[j]<=x;pe=pe*prm[j]){
			int tmp=pe%P;
			res=(res+1ll*tmp*(tmp-1)%P*g(x/pe,j)%P)%P;//f(p_j^e)*g(x/p_j^e,j)
			res=(res+1ll*tmp*prm[j]%P*(1ll*tmp*prm[j]%P-1)%P)%P;//f(p_j^(e+1))
		}
	return res;
}

int main(){
	scanf("%lld",&n);
	get_h();
	printf("%d
",((g(n,0))+1)%P);
}
原文地址:https://www.cnblogs.com/Y25t/p/13543488.html