GCD SUM

似乎很有趣的一道题目

题目要求的是

\[\sum\limits_{i=1}^n\sum\limits_{i=1}^{n}gcd(i,j) \]

假设我们有一个函数(借用了一下等于等于符号)

\[f(k)=\sum\limits_{i=1}^n\sum\limits_{i=1}^{n}gcd(i,j)==k \]

那么我们就要求

\[\sum\limits_{i=1}^nf(i)\times i \]

假如对于\(i\),有函数\(g(i)\)

\[g(k)=\sum\limits_{i=1}^n\sum\limits_{i=1}^{n}gcd(i,j)\%k==0 \]

显然会有:

\[g(k)=\sum\limits_{i=1}^{\lfloor\frac{m}{k}\rfloor}f(i\times k) \]

即是

\[f(i)=g(k)-\sum\limits_{i=2}^{\lfloor\frac{m}{k}\rfloor}f(i\times k) \]

\(g(i)\)是可以求的,因为当两个数gcd可以整除i,当且仅当两个数都除的尽i。而总共有:

\[\lfloor \frac{m}{i}\rfloor \]

个数可以除的尽i,所以运用一下排列组合的知识得到

\[g(i)=\lfloor \frac{m}{i}\rfloor\times\lfloor \frac{m}{i}\rfloor=\lfloor \frac{m}{i}\rfloor^2 \]

然后就可以从大到小线性求解了。

#include<cstdio>
//#define zczc
#define int long long
const int N=1000100;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}

int m,ans,f[N];

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	read(m);
	for(int i=m;i;i--){
		f[i]=m/i*(m/i);
		for(int j=i*2;j<=m;j+=i)f[i]-=f[j];
		ans+=f[i]*i;
	}
	printf("%lld",ans);
	
	return 0;
}
posted @ 2022-01-24 21:45  Feyn618  阅读(38)  评论(0编辑  收藏  举报