题目:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2421题意:
求所有gcd(i,j)的和,(1<=i<j<=N)N=4000000
思路:
神奇的数论题,首先很容易想到打表,只要求出每个i与小于它的数的gcd存在a[i]中,然后扫一遍b[i]=b[i-1]+a[i];就是答案。
关键在于怎么求a[i],要转换思维,不能求i与每个数的关系,而要找i与gcd结果就是那些约数的关系,当gcd(i,x)==t时,也就是gcd(i/t,x/t)==1,所以所有小于且互质于i/t的数与i的gcd都是t,也就是找到所有的约数t对于所有满足的数也就是i/t的欧拉数。如此得解,欧拉函数的运用。
代码:
#define N 4000010
long long a[N],b[N];
long long eul[N];
void init()
{
eul[1]=1;
for(long long i=2;i<N;i++)
eul[i]=i;
for(long long i=2;i<N;i++)
if(eul[i]==i)
for(long long j=i;j<N;j+=i)
eul[j]=eul[j]/i*(i-1);
memset(a,0,sizeof(a));
for(long long i=1;i<N;i++)
for(long long j=i*2;j<N;j+=i)
a[j]+=eul[j/i]*i;
b[0]=b[1]=0;
for(long long i=2;i<N;i++)
b[i]=b[i-1]+a[i];
}
int main()
{
int i,j,k,kk,t,x,y,z;
init();
while(scanf("%d",&x)!=EOF&&x)
printf("%lld\n",b[x]);
return 0;
}