Description
给出(n(nleq2 imes10^9)),求(sum_{i=1}^n varphi(i))。
Solution
杜教筛。
杜教筛的作用就是以一个低于(O(n))(准确来说是(O(n^{frac{2}{3}})))的时间复杂度来计算积性函数(f)的前缀和。
记(S(x)=sum_{i=1}^x f(i))。那么对于任意一个积性函数(g),我们有
[egin{align*}
sum_{i=1}^n (f imes g)(i) &= sum_{d=1}^n sum_{d|i} g(d)f(frac{n}{d}) \
&= sum_{d=1}^n g(d) sum_{i=1}^{lfloor frac{n}{d}
floor} f(i) \
&= sum_{d=1}^n g(d)S(lfloor frac{n}{d}
floor) \
&= g(1)S(n) + sum_{d=2}^n g(d)S(lfloor frac{n}{d}
floor) \
S(n) &= sum_{i=1}^n (f imes g)(i) - sum_{d=2}^n g(d)S(lfloor frac{n}{d}
floor)
end{align*}$$ 我们可以用整除分块来做后面的部分,那么如果我们能让前面的部分好算,就解决了。对于本题,因为有$varphi imes 1=id$,所以令$g(x)=1(x)$,就有$sum_{i=1}^n (varphi imes 1)(i)=sum_{i=1}^n i=dfrac{n(n+1)}{2}$。
<!-- 接下来我们来算一下复杂度。我们可以预处理$xleq n_1$范围内的$S(x)$,设计算$S(x)$的复杂度为$T(x)$,那么有
$$T(x)=left{egin{matrix}
O(1)+sqrt n T(dfrac{x}{i}) &(x>n_1)\
O(1) &(xleq n_1)
end{matrix}
ight.$$ -->根据我并不会算的复杂度,我们可以预处理出$xleq n^{frac{2}{3}}$内的所有$S(x)$,此时计算$S(n)$的复杂度也为$O(n^{frac{2}{3}})$。
我们发现我们会计算到$S(⌊dfrac{n}{2}⌋),S(⌊dfrac{⌊frac{n}{2}⌋}{2}⌋=⌊dfrac{n}{4}⌋),S(⌊dfrac{n}{3}⌋)...$这么一类数,即除了预处理的$S(1..n^{frac{2}{3}})$,还要计算$S(⌊dfrac{n}{1..n^{frac{1}{3}}}⌋)$这$n^{frac{1}{3}}$个数。记录$S_1(x)=S(⌊dfrac{n}{x}⌋)$,就可以进行记忆化搜索啦。
##Code
```cpp
//欧拉函数求和
#include <cstdio>
typedef long long lint;
const int N1=2e6;
int n0,n1;
int prCnt,pr[N1]; bool prNot[N1];
int phi[N1]; lint S[N1],S1[N1];
void init(int n)
{
phi[1]=1;
for(int i=2;i<=n;i++)
{
if(!prNot[i])
{
pr[++prCnt]=i; phi[i]=i-1;
for(lint j=1LL*i*i;j<=n;j*=i) phi[j]=phi[j/i]*(i-1);
}
for(int j=1;j<=prCnt;j++)
{
int x=i*pr[j]; if(x>n) break;
prNot[x]=true;
if(i%pr[j]) phi[x]=phi[i]*(pr[j]-1);
else {phi[x]=phi[i]*pr[j]; break;}
}
}
for(int i=1;i<=n;i++) S[i]=S[i-1]+phi[i];
}
lint sum(int n)
{
if(n<=n1) return S[n];
if(S1[n0/n]) return S1[n0/n];
lint r=n*(n+1LL)/2;
for(int L=2,R;L<=n;L=R+1)
{
int v=n/L; R=n/v;
r-=(R-L+1)*sum(v);
}
return S1[n0/n]=r;
}
int main()
{
scanf("%d",&n0);
for(n1=1;n1*n1*n1<=n0;n1++); n1*=n1;
init(n1);
printf("%lld
",sum(n0));
return 0;
}
```]