UVA 11426 GCD

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

Sample Output

67

13015

143295493160

题目大意:就是求G[n]
 
G[n] = gcd(1,2) + gcd(1,3) + ... + gcd(1,n-1) + gcd(1,n)
         +gcd(2,3) + gcd(2,4) + ... + gcd(2,n-1) + gcd(2,n)
         +...
         +gcd(n-2,n)+ gcd(n-1,n);
 
这样我们可以得到一个规律:
 
G[n] = G[n - 1] + b[n]( 其中b[n]就是上面红色部分的和b[n] = gcd(1,n) + gcd(2,n) + ... + gcd(n-1,n)  )
 
b[n] = gcd(1,n) + gcd(2,n) + ... + gcd(n-1,n) 
b[n]的加数我们可以统另为gcd(b, n);
 
设a[xi] 表示使gcd(b,n) = xi成立的b的个数
那么b[n] = a[xi]*xi = a[x1]*x1 + a[x2]*x2 + a[x3]*x3 +...+a[xs]*xs
我们就要求a[xi]
 
gcd(b,n) = xi可以转化为求有多少个b/xi使gcd(b/xi,n/xi)=xi/xi = 1,要求b/xi的个数就相当于求与n/xi互质的数有多少个(即求n/xi的欧拉函数)因为只有互质的两个数气最大公约数才是1
那么我们最终求得就是b[n] = a[n/xi] *1 * xi (i = 1,2,3,...)
 
 
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<algorithm>

using namespace std;

const int N = 4000010;
typedef long long ll;

ll a[N], b[N], G[N];

int main()
{
    ll n;
    for(ll i = 0 ; i < N ; i++)
        a[i] = i;//初始化
    a[1] = 1;
    for(ll i = 2 ; i < N ; i++)
    {
        if(a[i] == i)
        {
            a[i] -= a[i] / i;
            for(ll j = i * 2 ; j < N ; j += i)
                a[j] -= a[j] / i;
        }
    }//欧拉函数打表
    for(ll i = 1 ; i < N ; i++)
    {
        for(ll j = i * 2 ; j < N ; j += i)
            b[j] += a[j / i] * i;
    }//b[n]打表(这里b的下标应含因子i)
    G[2] = 1;
    for(ll i = 3 ; i < N ; i++)
        G[i] = G[i - 1] + b[i];//G[n]打表
    while(scanf("%lld", &n), n)
    {
        printf("%lld
", G[n]);
    }
    return 0;
}
 
 
原文地址:https://www.cnblogs.com/qq2424260747/p/4952923.html