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;
}
一如既往,万事胜意