Luogu P2568 GCD
题目链接:Click here
Solution:
我们尝试着转化一下式子
\[\sum_{p\in pri} \sum_{i=1}^n \sum_{j=1}^n [gcd(i,j)=p]\\
\sum_{p\in pri} \sum_{i=1}^{\lfloor {n\over p}\rfloor} \sum_{j=1}^{\lfloor {n\over p}\rfloor} [gcd(i,j)=1]\\
\]
后面一部分有些眼熟(要素察觉
\[\sum_{p\in pri} \sum_{i=1}^{\lfloor {n\over p}\rfloor} \sum_{j=1}^{\lfloor {n\over p}\rfloor} \sum_{d|i,d|j} \mu(d)\\
\sum_{p\in pri} \sum_{d=1}^{\lfloor {n\over p}\rfloor} \mu(d) {\lfloor {n\over pd}\rfloor}^2\\
T=dp\\
\sum_{T=1}^n {\lfloor {n\over T}\rfloor}^2\sum_{p|T,p\in pri} \mu({T\over p})
\]
我们令\(f(T)=\sum_{p|T,p\in pri} \mu({T\over p})\),考虑如何线筛
当\(T\in pri\),\(f(T)=1\)是十分显然的,考虑\(f(T\times p),p\in pri\)
经过简单推导可发现\(p|T\)时,\(f(T\times p)=\mu(T)\),否则\(f(T\times p)=-f(T)+\mu(T)\)
那么我们便可以愉快的数论分块了!时间复杂度\(O(\sqrt n+n)\)
正解phi?看到gcd就莫反的我是不是已经没救了
Code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e7+11;
bool vis[N];
int n,cnt,ans,p[N],u[N],f[N];
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
void prepare(){
u[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]) p[++cnt]=i,u[i]=-1,f[i]=1;
for(int j=1;j<=cnt&&i*p[j]<=n;j++){
vis[i*p[j]]=1;
if(i%p[j]==0){
f[i*p[j]]=u[i];
break;
}
u[i*p[j]]=-u[i];
f[i*p[j]]=-f[i]+u[i];
}
}
for(int i=1;i<=n;i++) f[i]+=f[i-1];
}
signed main(){
n=read();
prepare();
for(int i=1,j;i<=n;i=j+1){
j=n/(n/i);
int v=n/i;v=v*v;
ans+=(f[j]-f[i-1])*v;
}printf("%lld\n",ans);
return 0;
}