题意:求f(x)前n项和 f(x)=SUM(gcd(i,j)) (1<=i<j<=n)
题解:设g(n,i):与n的gcd为i的数有多少个。
那么最多可以有n/i个,这些数当中肯定有一些数与n的gcd是i的倍数。
我们可以想到与n/i互质的数的个数肯定就是我们要求的数,
比如:g(24,3),24可分解为3*3*3*3*3*3*3*3,3可分解为3,那么与8互质的数有1,3,5,7。那么这些数乘以三之后为3,9,15,21。
这些数字与24的gcd都是3,因为他们含有3的个数与24含有3的个数互质。而18含有6个3,gcd(6,8)=2; 那么18和24的最大公约数就是2*3=6,与一个数x互质的数的个数即为欧拉函数值。我们可以先打欧拉函数表ph,枚举j的因子i,然后求和i*ph[j/i]*i。
因为题目求的是前n项和,所以我们最后在求一个前缀和即可(注意用long long)。
#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
using namespace std;
#define maxn 4000005
typedef long long ll;
long long ph[maxn+10],a[maxn+10];long long f[maxn+10];
void phi_table()
{
memset(ph,0,sizeof(ph));
memset(a,0,sizeof(a));
ph[1]=1;
for(int i=2;i<=maxn;i++)
if(!ph[i])
for(int j=i;j<=maxn;j+=i)
{
if(!ph[j]) ph[j]=j;
ph[j]=ph[j]/i*(i-1);
}
//for(int i=1;i<=10;i++) printf("%d %d\n",i,ph[i]);
for(ll i=1;i<=maxn;i++)
{
for(ll j=i*2;j<=maxn;j+=i)
{
a[j]+=ph[j/i]*i;
}
}
for(ll i=1;i<=maxn;i++)
{
f[i]=f[i-1]+a[i];
}
}
int main()
{
phi_table();
int n;
while(cin>>n)
{
if(!n)break;printf("%lld\n",f[n]);
}
return 0;
}