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;
- }