suxxsfe

一言(ヒトコト)

杜教筛学习笔记

计算 \(S(n)=\sum_{i=1}^n f(i)\)

对于一个积性函数 \(g\),有(第二行是将 \(i,j\) 分别枚举 \(d,\frac{n}{d}\)

\[\begin{aligned}\sum_{i=1}^n (f*g)(i) &=\sum_{i=1}^n\sum_{d|i} f(d)g(\frac{i}{d})\\ &=\sum_{i=1}^n\sum_{j=1}^{\lfloor\frac{n}{i}\rfloor}g(i)f(j)\\ &=\sum_{i=1}^ng(i)S\left(\lfloor\frac{n}{i}\rfloor\right) \end{aligned} \]

然后把这个求和式的第一项拿出来,就有了:

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

这个就是杜教筛的主要套路了(

一般对这个 \(S\left(\lfloor\frac{n}{i}\rfloor\right)\) 整除分块来递归地求解

至于复杂度,线性筛预处理前 \(n^{\frac{2}{3}}\) 然后剩下的再递归求的复杂度是 \(O(n^{\frac{2}{3}})\)

多测的时候还可以开个 map 把已经求过的值存下来


一个模板题:https://www.luogu.com.cn/problem/P4213

\(\varphi\)

此时肯定要令 \(f=\varphi\),然后问题是如何找到一个合适的 \(g\)

由于想到 \(\varphi * \operatorname{1}=\operatorname{Id}\),所以可以令 \(g=\operatorname{1}\)

此时可以发现,\(g(i)\)\(\sum_{i=1}^n (f*g)(i)\) 都很好求,于是可以直接杜教筛

inline long long get_phi(int n){
	if(n<=maxn) return phi[n];
	if(ans_phi.find(n)!=ans_phi.end()) return ans_phi[n];
	long long ans=((long long)n*(n+1ll))>>1;
	for(reg unsigned int l=2,r;l<=n;l=r+1){
		r=n/(n/l);
		ans-=(r-l+1)*get_phi(n/l);
	}
	return ans_phi[n]=ans;
}

\(\mu\)

\(f=\mu,g=\operatorname{1}\),于是就有 \(f*g=\epsilon\)

那就做完了

inline int get_mu(int n){
	if(n<=maxn) return mu[n];
	if(ans_mu.find(n)!=ans_mu.end()) return ans_mu[n];
	long long ans=1;
	for(reg unsigned int l=2,r;l<=n;l=r+1){
		r=n/(n/l);
		ans-=(r-l+1)*get_mu(n/l);
	}
	return ans_mu[n]=ans;
} 

总而言之就是想办法找 \(g\)

P3768 简单的数学题 推完式子有一部分是 \(\varphi(k)k^2\) 的前缀和,于是就可以构造 \(f=\operatorname{Id}^2\cdot \varphi,g=\operatorname{Id}^2\),然后就能发现 \(\sum_{i=1}^n (f*g)(i)=n^3\)

\(\epsilon=\mu * 1\)
\(d=1 * 1\)
\(\sigma=\operatorname{id} * 1\)
\(\varphi=\mu * \operatorname{id}\)
\(\operatorname{id}=\varphi * 1\)

posted @ 2021-03-18 20:24  suxxsfe  阅读(65)  评论(0编辑  收藏  举报