UVA 11426 GCD - Extreme (II)(欧拉函数)

来源:互联网 发布:c语言 运算符 编辑:程序博客网 时间:2024/05/17 07:54

题意:给出正整数n,求gcd(1,2)+gcd(1,3)+gcd(2,3)……+gcd(n-1,n),即求求sum( gcd(i,j) , 1<=i<j<=n )1<n<4000001

思路:

设f[n] = gcd(1,n)+gcd(2,n)+……+gcd(n-1,n)

所以要求的结果就是s[n]  =  f[1] + f[2] +……+  f[n],所以结果s[n] = s[n-1] + f[n]

gcd(x,n)=i是n的约数(x<n),所以可以按照这个约数进行分类。设gcd(x,n)=i的个数为g(n,i),则有f[n] = sum( i*g(n,i) )。
这个gcd(x,n) = i等价于gcd(x/i,n/i) = 1,因此满足条件的 x/i 有 phi(n/i) 个(欧拉函数的定义),所以就是欧拉函数的求phi表了。

然后求f[n],这儿要对于每个 i 枚举其倍数n

#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int N = 4000000;typedef long long ll;ll s[N+5],f[N+5];int phi[N];void phi_table(int n){    for(int i = 2;i <= n;i++)        phi[i] = 0;    phi[1] = 1;    for(int i = 2;i <= n;i++)    {        if(!phi[i])        {            for(int j = i;j <= n;j+=i)            {                if(!phi[j])                    phi[j] = j;                phi[j] = phi[j] / i * (i-1);            }        }    }}int main(){    phi_table(N);    memset(f,0,sizeof(f));    for(int i = 1;i <= N;i++)        for(int n = i*2;n <= N;n+=i)        f[n] += i * phi[n / i];    //预处理    s[2] = f[2];    for(int n = 3;n <= N;n++)        s[n] = s[n-1] + f[n];    int n;    while(~scanf("%d",&n) && n)    {        printf("%lld\n",s[n]);    }    return 0;}


0 0
原创粉丝点击