题目大意:
输入n(2<=n<=4000000)输出gcd(i, j) (1<=i<j<=n)的和。
gcd(1, 2) +
gcd(1, 3) + gcd(2, 3) +
gcd(1, 4) + gcd(2, 4)+ gcd(3, 4) +
+......+
…… + gcd(n-1, n)
设:f(n) = gcd(1, n)+gcd(2, n)+gcd(3, n)+ … + gcd(n-1, n)
设: S(n)= f(2)+f(3)+ … + f(n)
那么:S(n)=s(n-1)+f(n)
我们把f(n)求出来,再递推一下。
对于:gcd(x, n)= i, 那么i一定是n的因数。
假设:g(n, i) 表示满足gcd(x, n)=i 并且x<n的个数。
那么:f(n) = i*gcd(n, i) i是n的约数
gcd(x, n)= i 等价gcd(x/i, n/i)=1。
所有gcd(x, n)= i等于gcd(x/i, n/i)=1的个数。g(n, i)=phi[n/i]
Phi[] 欧拉函数。
所以:f(n) = i* Phi[n/i] i是n的约数
我们对于每个i枚举倍数n。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=4000000;
LL euler[N+5];//存储欧拉函数值
LL s[N+5], f[N+5];
void Init()
{
euler[1]=1;
for(int i=2;i<N;i++)
euler[i]=i;
for(int i=2;i<N;i++) {
if(euler[i]==i)
{
for(int j=i;j<N;j+=i)
euler[j]=euler[j]/i*(i-1);
}
}
}
int main()
{
Init();
memset(f, 0, sizeof(f));
for(int i=1; i<=N; i++){
for(int n=i*2; n<=N; n+=i){//n!=i, 因为gcd(x, n)=i x<n。所以:n>i
f[n]+=i*euler[n/i];
}
}
s[2]=f[2];
for(int n=3; n<=N; n++){
s[n]=s[n-1]+f[n];
}
int n;
while(scanf("%d", &n), n){
printf("%lld\n", s[n]);
}
return 0;
}