杜教筛
又在抄 oi-wiki...
\[\phi(n)=\sum_i^n \varphi(i) \]利用 \(id=\varphi * 1\):
\[\begin{aligned} \frac{1}{2}n(n+1)&=\sum_k^n k \\ &=\sum_k^n\sum_{d|k}\varphi(\frac{k}{d}) \\ &=\sum_d^n\sum_{1\leq k\leq n,d|k}\varphi(\frac{k}{d}) \\ &=\sum_d^n\sum_k^{\left\lfloor\frac{n}{d}\right\rfloor}\varphi(k) \\ &=\sum_d^n\phi(\left\lfloor\frac{n}{d}\right\rfloor) \end{aligned} \]注意到当 \(d=1\) 的时候就是我们想要的 \(\phi(n)\)
即:\(\phi(n)=\frac{1}{2}n(n+1)-\sum_{d\geq 2}\phi(\left\lfloor\frac{n}{d}\right\rfloor)\)
记忆化搜索即可,可证算法复杂度为 \(\mathcal{O}(n^{2/3})\).
一般化
欲求 \(f\) 的前缀和 \(F\),构造出 \(F(n)\) 关于 \(F(\left\lfloor\frac{n}{d}\right\rfloor)\) 的递推式。
\[\begin{aligned} \sum_i \sum_{d|i}g(d)f(\frac{i}{d})=\sum_{i}g(i)F(\left\lfloor\frac{n}{i}\right\rfloor) \\ \Longleftrightarrow \sum_i(f\ast g)(i)=g(1)F(n)+\sum_{i>1}g(i)F(\left\lfloor\frac{n}{i}\right\rfloor) \end{aligned} \]若能快速求得 \(f\ast g\) 的前缀和以及 \(g\),则可以整除分块来求 \(F(n)\).
试试看!
求 \(\sum_{i=1}^n\mu(i)\) 的值,其中 \(n\leq 2^{31}-1\).
利用 \(\mu \ast 1=\epsilon\) 即可。