Problem J GCD Extreme (II)
Input: Standard Input
Output: Standard Output
Given the value of N, you will have to find the value of G. The definition of G is given below:
Here GCD(i,j) means the greatest common divisor of integer i and integer j.
For those who have trouble understanding summation notation, 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 100 lines of inputs. Each line contains an integer N (1<N<4000001). 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
10
100
200000
0
Output for Sample Input
67
13015
143295493160
/* 题目大意给出一个n,求sum(gcd(i,j),0<i<j<=n); 可以明显的看出来s[n]=s[n-1]+f[n]; f[n]=sum(gcd(i,n),0<i<n); 现在麻烦的是求f[n] gcd(x,n)的值都是n的约数,则f[n]= sum{i*g(n,i),i是n的约数},注意到gcd(x,n)=i的 充要条件是gcd(x/i,n/i)=1,因此满足条件的 x/i有phi(n/i)个,说明gcd(n,i)=phi(n/i). f[n]=sum{i*phi(n/i),1=<i<n} 因此可以搞个for循环对i循环,只要i<n,f[n]+=i*phi(n/i); */ #include<iostream> #include<cstdio> using namespace std; #define Max 4000000 __int64 s[Max+5],f[Max+5],phi[Max+5]; int prime[Max/10]; bool flag[Max+5]; void Init() { int i,j,num=0; memset(flag,1,sizeof(flag)); phi[1]=1; for(i=2;i<=Max;i++)//欧拉筛选 { if(flag[i]) { prime[num++]=i; phi[i]=i-1; } for(j=0;j<num && prime[j]*i<=Max;j++) { flag[i*prime[j]]=false; if(i%prime[j]==0) { phi[i*prime[j]]=phi[i]*prime[j]; break; } else phi[i*prime[j]]=phi[i]*(prime[j]-1); } } memset(f,0,sizeof(f)); for(i=1;i<=Max;i++)//f[n]更新 { //因为f[n]=gcd[1,n]+....+gcd[n-1,n]所以j=2*i开始,若从j=i开始那就等同于加上了一项gcd(n,n) for(j=2*i;j<=Max;j+=i) f[j]+=i*phi[j/i]; } memset(s,0,sizeof(s)); for(i=2;i<=Max;i++) s[i]=s[i-1]+f[i]; } int main() { Init(); int n; while(cin>>n,n) printf("%I64d ",s[n]); return 0; }