大意:给定正整数N,求出
for(i=1;i<N;i++)
for(j=i+1;j<=N;j++)
G+=gcd(i,j);
G的值。
这道题目的意思就是(i,N)各个数的之间的最大公约数之和。
这道题目有点小想法加上xjb乱搞 假设x,y互素,所以gcd(k*x,k*y)=k;
所以就是求每一个数的欧拉函数,然后再跟新后的区间,a[j * i] += j * phi[i];
细想一下是不会有重复部分的,欧拉函数是N与(1~N-1)互素的个数,题目求的是1~N之间两两之间,范围刚好是前面之和;
所以就是用个欧拉筛然后每次往后跟新就可以了。暴力打一次表,然后就是O(1)。
#include<stdio.h>
#include<string.h>
#include <iostream>
using namespace std;
#define MAXD 4000010
const int N = 4000000;
typedef long long LL;
int phi[MAXD];
LL a[MAXD];
void prep()
{
memset(a, 0, sizeof(a));
for(int i = 1; i <= N; i ++)
phi[i] = i;
for(int i = 2; i <= N; i ++)
{
if(phi[i] == i){ ///质数
for(int j = i; j <= N; j += i){
phi[j] = phi[j] / i * (i - 1);
}
}
for(int j = 1; j * i <= N; j ++)
a[j * i] += j * phi[i]; ///通过对i*j的质因子来求
}
for(int i = 1; i <= N; i ++)
a[i] += a[i - 1];
}
int main()
{
prep();
int n;
while(scanf("%d", &n), n)
printf("%lld\n", a[n]);
return 0;
}