求s(x)=sum(gcd(i,j)) 其中j<=x i<j
我们可以设f(x) 为 sum(gcd(i,x)) 其中i<x
则问题转化为s(x)=f(1)+......f(x);
再设g(x,i)表示gcd(k,x)=i的数量 k<x 则 f(x)=sum(g(x,i)*i) i为x的约数
我们可以看到x与k的最大公约数为i 那么 x/i 与 k/i互质 那么g(x,i)=phi(x/i)但是对于每一个f(x)我们枚举i则显得效率非常的低,这时候我们可以采用一种类似素数筛选的策略,以i为基础上相增加倍数,初始化数组f,问题就打打的简化了
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 4000000
int phi[MAXN+10];
void phi_table(int n){
for(int i = 2; i <= n; i++) phi[i] = 0;
phi[1] = 1;
for(int i = 2; i <= n; i++) if(!phi[i])
for(int j = i; j <= n; j += i) {
if(!phi[j]) phi[j] = j;
phi[j] = phi[j] / i * (i-1);
}
}
typedef long long LL;
LL s[MAXN] ,f[MAXN];
int n;
int main(){
phi_table(MAXN);
f[0]=0;
f[1]=0;
memset(f,0,sizeof(f));
for(int i=1;i<=MAXN;i++)
for(int j=i*2;j<=MAXN;j+=i)
f[j]+=(LL)phi[j/i]*i;
s[0]=s[1]=0;
for(int i=2;i<=MAXN;i++)
s[i]=s[i-1]+f[i];
while(cin>>n&&n)
cout<<s[n]<<endl;
return 0;
}