P4213 【模板】杜教筛(Sum)(杜教筛)

根据狄利克雷卷积的性质,可以在低于线性时间复杂度的情况下,求积性函数前缀和
#### 公式 $$ 求\sum_{i=1}^{n}\mu(i) $$

因为\(\mu*I=\epsilon\)

所以设\(h=\mu*I,S_n=\sum_{i=1}^n\mu(i)\)

\[\sum_{i=1}^{n}h(i)\]

\[=\sum_{i=1}^{n}\sum_{d|i}\mu(\lfloor\frac{i}{d}\rfloor)\times I(d) \]

\[=\sum_{i=1}^nI(i)\sum_{j=1}^{\lfloor \frac{n}{i}\rfloor}\mu(j) \]

\[=\sum_{i=1}^nI(i)\times S(\lfloor\frac{n}{i}\rfloor) \]

\[=I(1)\times S(n)+\sum_{i=2}^nI(i)\times S(\lfloor\frac{n}{i}\rfloor)\]

\[I(1)\times S(n)=\sum_{i=1}^{n}h(i)-\sum_{i=2}^{n}S(\lfloor\frac{n}{i}\rfloor) \]

\[S(n)=1-\sum_{i=2}^n{S(\lfloor\frac{n}{i}\rfloor)} \]

\[求\sum_{i=1}^n\phi(i) \]

因为\(\phi*I=id\)

所以设\(h=\phi*I,S_n=\sum_{i=1}^n\phi_i\)

\[\sum_{i=1}^nh(i)$$$$=\sum_{i=1}^n\sum_{d|i}\phi(\lfloor\frac{i}{d}\rfloor)\times I(d)$$$$=\sum_{i=1}^nI(i)\times \sum_{d|i}\phi(\lfloor\frac{i}{d}\rfloor)$$$$=\sum_{i=1}^nI(i)\times \sum_{t=1}^{\lfloor\frac{n}{i}\rfloor}\phi(t)$$\]

=\sum_{i=1}^nI(i)\times S(\lfloor\frac{n}{i}\rfloor)$$$$
=I(1)\times S(n)+\sum_{i=2}^n I(i)\times S(\lfloor\frac{n}{i}\rfloor)

\[\]

S(n)=\sum_{i=1}nh(i)-\sum_{i=2}n I(i)\times S(\lfloor\frac{n}{i}\rfloor)

\[\]

S(n)=\frac{(n+1)\times n}{2}-\sum_{i=2}^n I(i)\times S(\lfloor\frac{n}{i}\rfloor)

\[#### 注意事项 - 尽量减少常数 - 开头线性筛预处理的时候尽量开到$n^{\frac{2}{3}}$或更大 - long long和int要区别 - 枚举2 TO N 可以整除分块 #### 代码 ```cpp #include <cstdio> #include <cstring> #include <algorithm> #include <unordered_map> using namespace std; const int MAXN = 5000000; unordered_map<int,long long> Sumphi; unordered_map<int,long long> Summu; int iprime[MAXN+5],cnt; long long mu[MAXN+5],phi[MAXN+5]; bool isprime[MAXN+5]; void prime(int n){ isprime[1]=true; mu[1]=1; phi[1]=1; for(int i=2;i<=n;i++){ if(!isprime[i]) iprime[++cnt]=i,phi[i]=i-1,mu[i]=-1; for(int j=1;j<=cnt&&iprime[j]*i<=n;j++){ isprime[iprime[j]*i]=true; mu[iprime[j]*i]=-mu[i]; phi[iprime[j]*i]=phi[i]*(iprime[j]-1); if(i%iprime[j]==0){ mu[iprime[j]*i]=0; phi[iprime[j]*i]=phi[i]*(iprime[j]); break; } } } for(int i=1;i<=n;i++){ mu[i]+=mu[i-1]; phi[i]+=phi[i-1]; } } long long djsmu(int n){//first mu second phi if(n<=MAXN) return mu[n]; if(Summu.count(n)) return Summu[n]; int mid1=0; for(int i=2,j;i<=n;i=j+1){ j=min(n/(n/i),n); mid1+=(j-i+1)*djsmu(n/i); } Summu[n]=1-mid1; return Summu[n]; } long long djsphi(int n){//first mu second phi if(n<=MAXN) return phi[n]; if(Sumphi.count(n)) return Sumphi[n]; long long mid1=0; for(int i=2,j;i<=n;i=j+1){ j=min(n/(n/i),n); mid1+=(j-i+1)*djsphi(n/i); } Sumphi[n]=1LL*(n+1)*n/2-mid1; return Sumphi[n]; } int main(){ prime(MAXN); int T,n; scanf("%d",&T); for(int i=1;i<=T;i++){ scanf("%d",&n); printf("%lld %d\n",djsphi(n),djsmu(n)); } return 0; } ```\]

posted @ 2018-12-06 17:26  dreagonm  阅读(339)  评论(0编辑  收藏  举报