UVA 11426 GCD

转载请注明出处: http://www.cnblogs.com/fraud/           ——by fraud

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     Output for Sample Input

10

100

200000

0

 

67

13015

143295493160

 


Problemsetter: Shahriar Manzoor

Special Thanks: SyedMonowarHossain

设dp[i]=gcd(1,i)+gcd(2,i)+……+gcd(i-1,i);

则ans[n]=dp[2]+dp[3]+……+dp[n].

由此问题已经转化成如何求dp[i]了,即需要求1到i-1所有数与i的gcd的和。

设k为满足gcd(x,i)=j且x<i的正整数的个数,则dp[i]=∑j*k;

同时,由于gcd(x,i)=j等价于gcd(x/j,i/j)=1,也就是phi[i/j];

接下来反过来求,那就不需要分解素因子了

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 typedef long long ll;
 5 const int maxn=4000010;
 6 int phi[maxn];
 7 ll dp[maxn+1];
 8 ll ans[maxn+1];
 9 void phi_table()
10 {
11     phi[1]=1;
12     for(int i=2;i<maxn;i++)
13     {
14         if(!phi[i])
15         {
16             for(int j=i;j<maxn;j+=i)
17             {
18                 if(!phi[j])phi[j]=j;
19                 phi[j]=phi[j]/i*(i-1);
20             }
21         }
22     }
23 }
24 int main()
25 {
26     ios::sync_with_stdio(false);
27     phi_table();
28     for(int i=1;i<maxn;i++)
29     {
30         for(int j=i*2;j<maxn;j+=i)dp[j]+=(long long)i*(long long)phi[j/i];
31     }
32     ans[2]=dp[2];
33     for(int i=3;i<maxn;i++)ans[i]=ans[i-1]+dp[i];
34     int n;
35     while(cin>>n&&n)
36     {
37         cout<<ans[n]<<endl;
38     }
39     return 0;
40 }
View Code
原文地址:https://www.cnblogs.com/fraud/p/4103403.html