您的位置:首页 > 其它

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

2013-07-26 10:30 351 查看
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
=s[n-1]+f
;
f
=sum(gcd(i,n),0<i<n);
现在麻烦的是求f

gcd(x,n)的值都是n的约数,则f
=
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
=sum{i*phi(n/i),1=<i<n}
因此可以搞个for循环对i循环,只要i<n,f
+=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
更新
{
//因为f
=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\n",s
);
return 0;
}


[align=center] [/align]
[align=center] [/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: