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
#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;
}