[bzoj 2818]欧拉函数

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2818

枚举最大公约数,对于每一个质数p,只需要求出1<=x,y<=(n/p)范围内gcd(x,y)=1的对数,而这个对数就是类似欧拉函数的一个前缀和。

#include<cstdio>
#include<cstring>
using namespace std;

const int maxn=10000005;
bool check[maxn];
int prime[maxn];
long long phi[maxn];
long long prephi[maxn];

void getPrime()
{
    int N=10000000;
    memset(check,false,sizeof(check));
    prime[0]=0;
    phi[1]=1;
    for (int i=2;i<=N;i++)
    {
        if (!check[i])
        {
            prime[++prime[0]]=i;
            phi[i]=i-1;
        }
        for (int j=1;j<=prime[0];j++)
        {
            if (i*prime[j]>N) break;
            check[i*prime[j]]=true;
            if (i%prime[j]==0)
            {
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            else
            {
                phi[i*prime[j]]=phi[i]*(prime[j]-1);
            }
        }
    }
    prephi[1]=phi[1];
    for (int i=2;i<=N;i++) prephi[i]=prephi[i-1]+2ll*phi[i];
}

int main()
{
    getPrime();
    int n;
    scanf("%d",&n);
    long long ans=0;
    for (int i=1;i<=prime[0];i++)
    {
        if (prime[i]>n) break;
        int r=n/prime[i];
        ans+=prephi[r];
    }
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2017-08-17 21:55  ACMsong  阅读(151)  评论(0编辑  收藏  举报