公式
\[ 求\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 可以整除分块
代码
#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;
}