uva 11426 线性欧拉函数筛选+递推

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;
}
 
 
原文地址:https://www.cnblogs.com/xiong-/p/3216539.html