UVa11426

GCD Extreme (II)

 

Given the value of N, you will have to find the value of G. The definition of G is given below:

uva 11426 - GCD - Extreme (II)" v:shapes="_x0000_i1025">

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<<span class="SpellE">N;i++)

for(j=i+1;j<=N;j++)

{

    G+=gcd(i,j);

}

 

 

Input

The input file contains at most 100 lines of inputs. Each line contains an integer N (1 

 

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,求gcd(1,2)+gcd(1,3)+gcd(2,3)+…+gcd(n-1,n),即所有满足1<=i<j<=n的数对(i,j)所对应的gcd(i,j)之和。

分析:

       设f(n) = gcd(1,n)+gcd(2,n)+…+gcd(n-1,n),则所求答案就是S(n)=f(2)+f(3)+…f(n)。

只要求出f(n),就可以得到答案S(n) = S(n-1)+f(n)。

       注意到所有的gcd(x,n)都是n的约数,可以按照这个约数进行分类,用g(n,i)表示满足gcd(x,n)=i的不大于n的正整数x的个数,则f(n)=sum{i*g(n,i)|i是n的约数}。注意到gcd(x,n)=i的充要条件是gcd(x/I,n/i)=1,所以g(n,i)=phi(n/i)。

       我们不需要对每一个n都枚举其约数i。可以反过来思考,对于每一个i,枚举其倍数n并更新f(n)的值那么时间复杂度将与筛法同阶。

 1 #include <cstdio>
 2 #include <cstring>
 3 const int maxn = 4000000;
 4 typedef long long LL;
 5 LL S[maxn + 1],f[maxn + 1];
 6 int phi[maxn];
 7 void phi_table(int n){
 8     for(int i = 2 ; i <= n ; i++) phi[i] = 0;
 9     phi[1] = 1;
10     for(int i = 2; i <= n ; i++) if(!phi[i])
11         for(int j = i ; j <= n ; j += i){
12             if(!phi[j]) phi[j] = j;
13             phi[j] = phi[j] / i * (i - 1);
14         }
15 }
16 int main(){
17     phi_table(maxn);
18     // 预处理f
19     memset(f,0,sizeof f);
20     for(int i = 1 ; i <= maxn ; i++)
21         for(int n = i * 2 ; n <= maxn ; n += i) f[n] += i * phi[n / i];
22     // 预处理S
23     S[2] = f[2];
24     for(int n = 3 ; n <= maxn ; n++) S[n] = S[n - 1] + f[n];
25     int n;
26     while(scanf("%d",&n) == 1 && n)
27         printf("%lld\n",S[n]);
28     return 0;
29 }
View Code

 

posted @ 2016-08-25 15:21  Yan_Bin  阅读(271)  评论(0编辑  收藏  举报