fzu1969 GCD Extreme 类似于uva10561
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
题意:给出数字n,求对于所有满足1<= i < j <= n 的所有数对,(i,j)所对应的gcd(i,j)之和。
思路:设f(n) = gcd(1,n)+gcd(2,n)+gcd(3,n)+。。。+gcd(n-1,n)。则所求答案s(n)=f(2)+f(3)+f(4)+。。。+f(n)。
注意到所有的gcd(x,n)的值都是n的约数,所以可以按照这个约数来进行分类。用g(n,i)来表示满足gcd(x,n)=i且x<n的正整数x的个数。则f(n)={i×g(n,i)|i为n的约数}。注意,g(n,i)=phi(n,i)。
如果对于每个n都枚举i,按照数据范围来看肯定会超时,我们不如反着来,先枚举i,再找i的倍数n。这样时间复杂度会进一步减少。
1 /* 2 * Author: Joshua 3 * Created Time: 2014年09月07日 星期日 19时26分30秒 4 * File Name: fzu1969.cpp 5 */ 6 #include<cstdio> 7 #include<cstring> 8 typedef long long LL; 9 #define maxn 1000005 10 int phi[maxn],a[maxn],f[maxn]; 11 LL s[maxn]; 12 bool p[maxn]; 13 int tot=0; 14 15 void pri() 16 { 17 memset(p,1,sizeof(p)); 18 for (int i=2;i<maxn;++i) 19 if (p[i]) 20 { 21 for (int j=i<<1;j<maxn;j+=i) 22 p[j]=false; 23 } 24 for (int i=2;i<maxn;++i) 25 if (p[i]) a[++tot]=i; 26 } 27 28 void phi_table() 29 { 30 for (int i=2;i<maxn;++i) 31 { 32 phi[i]=i; 33 int temp=i; 34 for (int j=1;j<=tot;++j) 35 { 36 if (temp==1) break; 37 if (p[temp]) 38 { 39 phi[i]/=temp; 40 phi[i]*=temp-1; 41 break; 42 } 43 if (temp % a[j] == 0) 44 { 45 phi[i]/=a[j]; 46 phi[i]*=a[j]-1; 47 while (temp%a[j]==0) temp/=a[j]; 48 } 49 } 50 } 51 } 52 53 void solve() 54 { 55 pri(); 56 phi_table(); 57 for (int i=1;i<maxn;++i) 58 for (int j=i;j<maxn;j+=i) 59 f[j]+=i*phi[j/i]; 60 for (int i=1;i<maxn;++i) 61 s[i]+=s[i-1]+f[i]; 62 } 63 64 int main() 65 { 66 int n; 67 solve(); 68 while (scanf("%d",&n) && n) 69 printf("%lld\n",s[n]); 70 return 0; 71 }