Problem Description
Given the value of N, you will have to find the value of G. The meaning of G is given in the following code
G=0;
for(i=1;i<N;i++)
for(j=i+1;j<=N;j++)
G+=gcd(i,j);
/*Here gcd() is a function that finds the greatest common divisor of the two input numbers*/
Input
The input file contains at most 20000 lines of inputs. Each line contains an integer N (1<N <1000001). The meaning of N is given in the problem statement. Input is terminated by a line containing a single zero.
Output
For each line of input produce one line of output. This line contains the value of G for the corresponding N. The value of G will fit in a 64-bit signed integer.
Sample Input
Sample Output
Source
Contest for 2010 lecture II
//一道很不错的数论题,在UESTC OJ和SPOJ上都有,都分别测试了下!
//针对题目开始给出的公式可以转换为是给出一个n,求
for(m=1;m<=n;m++)
每一个m值与它(不包括自身)之前所有数的公约数之和。
显然直接对每一个m从1-(m-1)循环每次求出最大公约数的时间复杂度是O(n^2)肯定TLE.。 由于m从1循环到n,而求m与它之前的数最大公约数又是从1循环到(m-1),其中有很多公约数的重复的计算,那么可以换个角度考虑,考虑一个数d它可以做哪些数的最大公约数,则枚举公约数d (1~n),d一共出现了sigma(phi(i))-1 (1<=i<=[N/d])次 ,而
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<algorithm>
#include<ctime>
using namespace std;
#define maxn 1000005
#define LL long long
int phi[maxn];
LL sumphi[maxn];
void Init()
{
int i,j;
memset(sumphi,0,sizeof(sumphi));
for(i=1;i<maxn;i++) phi[i]=i;
for(i=2;i<maxn;i++)
if(phi[i]==i)
for(j=i;j<maxn;j+=i)
phi[j]=phi[j]/i*(i-1);
for(i=1;i<maxn;i++)
sumphi[i]=sumphi[i-1]+phi[i];
}
int main()
{
Init();
int t,n,i,j;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
LL G=0;
for(i=1;i<=n;i++)
G+=i*(sumphi[n/i]-1); //计算每个最大公约数d出现的次数
printf("%lld\n",G);
}
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<algorithm>
#include<ctime>
using namespace std;
#define maxn 1000005
#define LL __int64
int phi[maxn];
LL ans[maxn]; //ans[x]=sum(ans[i]*j); (i*j=x)
void Init()
{
int i,j,k;
for(i=2;i<maxn;i++) phi[i]=i;
for(i=2;i<maxn;i++)
if(phi[i]==i)
for(j=i;j<maxn;j+=i)
phi[j]=phi[j]/i*(i-1);
for(i=2;i<maxn;i++)
ans[i]=phi[i];
for(i=2;i<=1000;i++)
{
ans[i*i]+=phi[i]*i;
for(j=i*i+i,k=i+1;j<maxn;j+=i,k++)
ans[j]+=i*phi[k]+k*phi[i]; //i*k=j,预处理出i,k可以作为哪些数j的最大公约数
}
for(i=1;i<maxn;i++)
ans[i]+=ans[i-1];
}
int main()
{
Init();
int n;
while(scanf("%d",&n),n)
printf("%I64d\n",ans[n]);
return 0;
}