[学习笔记] 杜教筛

好久以前就写过了,但是现在才搞懂原理。

前置知识

首先称一个函数 (f(x))积性函数 ,当且仅当对于任意两个互质的数 (a,b) ,有:

[f(ab)=f(a)f(b) ]

更特殊地,称一个函数 (f(x))完全积性函数 ,当且仅当对于任意 (a,b) ,有:

[f(ab)=f(a)f(b) ]

常见的积性函数有 (mu,varphi,sigma,d) ,完全积性函数有:(epsilon,I,id)

(epsilon(n)=[n=1],I(n)=1,id(n)=n)

对于两个函数 (f,g) ,定义他们的 迪利克雷卷积 为:

[(f*g)(i)=sum_{d|i}f(d) imes g(frac{i}{d}) ]

对于上面我们已经给出函数,有这样一些卷积关系是:

[mu*I=epsilon ]

[varphi*I=id ]

[mu*id=varphi ]

补充一个东西,(sum_{x|n}varphi(x)=n) 的证明,考虑两个互质的数 (m,n) ,有:

[sum_{x|n}sum_{y|m}varphi(x)varphi(y)=sum_{x|n}sum_{y|m}varphi(xy)=sum_{x|nm}varphi(x) ]

这说明了 (f(x)=sum_{x|n}varphi(x)) 是一个积性函数,对于质数有 (f(p_i^{k_i})=p_i^{k_i}) ,那么 (f(n)=n)

杜教筛

他是用来解决这样一个问题:$$sum_{i=1}^nf(i)=S(n)$$ ,做法是找一个 辅助函数 (g) ,也就是我们先求出 (f*g) 的前缀和,再算 (f) 的前缀和,选取 (g) 的标准就是 (f*g)(g) 的前缀和都是很好算的 ,先来推柿子:

[sum_{i=1}^n(f*g)(i)=sum_{i=1}^nsum_{d|i}f(d)g(frac{i}{d}) ]

然后套路地枚举 (d) (这种东西莫比乌斯反演的时候都见惯了):

[=sum_{d=1}^ng(d)sum_{i=1}^{n/d}f(i)=sum_{d=1}^ng(d)S(frac{n}{d}) ]

考虑 用前缀和来表示单个项 (g(1)S(n)) ,因为前缀和是好算的:

[g(1)S(n)=sum_{i=1}^ng(i)S(frac{n}{i})-sum_{i=2}^ng(i)S(frac{n}{i})=sum_{i=1}^n(f*g)(i)-sum_{i=2}^ng(i)S(frac{n}{i}) ]

假定前面的项是好算的,后面的项可以用数论分块来解决,容易发现我们得到了一个递归的问题。

模板题

[模板]杜教筛

(mu) 的前缀和

考虑到莫比乌斯反演的那个柿子:(mu*I=epsilon) ,令 (f=mu,g=I,f*g=epsilon)

ll get_mu(int n)
{
	if(n<=N) return mu[n];//这里是预处理的mu
	if(smu[n]) return smu[n];//这里是map记忆化
	ll ans=1;//f*g的前缀和
	for(int l=2,r;r<inf && l<=n;l=r+1)//数论分块
	{//这道题要卡 inf,因为可能加爆 
		r=n/(n/l);
		ans-=(r-l+1)*get_mu(n/l);//I的求和是r-l+1,然后递归
	}
	return smu[n]=ans;//得到答案
}

(varphi) 的前缀和

考虑到欧拉反演的柿子:(varphi*I=id) ,令 (f=varphi,g=I,f*g=id)

(id) 的前缀和特别好算,就是:(frac{n(n+1)}{2})

ull get_ph(int n)
{
	if(n<=N) return phi[n];//这里是预处理的phi
	if(sph[n]) return sph[n];//map记忆化
	ull ans=(ull)n*(n+1ll)/2;//要开ull
	for(int l=2,r;r<inf && l<=n;l=r+1)//数论分块
	{
		r=n/(n/l);
		ans-=(r-l+1)*get_ph(n/l);//I的求和是r-l+1,然后递归
	}
	return sph[n]=ans;//得到答案
}

扩展:(varphicdot id) 的前缀和

需要说明一下:(varphicdot id=sum_{i=1}^nvarphi(i)i)

(f=varphicdot id)(g=id)(f*g=(varphicdot i)*i) ,我们来看这个东西的前缀和好不好算:

[(f*g)(n)=sum_{d|n}(varphi(d) imes d) imes(frac{n}{d})=nsum_{d|n}varphi(d)=n^2 ]

最后一步是欧拉反演,所以他的前缀和是 (frac{n(n+1)(2n+1)}{6})

现在做一个小总结吧,杜教筛的关键是找辅助函数,让前缀和变得好算。

其他例题

简单的数学题

这两个是一类题,都是函数结构递归,然后杜教筛处理边界:循环之美,DZY Loves Math IV

原文地址:https://www.cnblogs.com/C202044zxy/p/14351712.html