BZOJ 4805 欧拉函数求和

Posted on 2017-04-06 09:54  ziliuziliu  阅读(192)  评论(0编辑  收藏  举报

裸的杜教筛。

注意long long。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define maxn 5000050
using namespace std;
long long n,prime[maxn],tot=0,phi[maxn];
bool vis[maxn];
map <long long,long long> mp;
void get_table()
{
    phi[1]=1;
    for (long long i=2;i<=maxn-50;i++)
    {
        if (!vis[i]) {prime[++tot]=i;phi[i]=i-1;}
        for (long long j=1;j<=tot && i*prime[j]<=maxn-50;j++)
        {
            vis[i*prime[j]]=true;
            if (i%prime[j]) {phi[i*prime[j]]=phi[i]*(prime[j]-1);continue;}
            else {phi[i*prime[j]]=phi[i]*prime[j];break;}
        }
    }
    for (long long i=1;i<=maxn-50;i++) phi[i]+=phi[i-1];
}
long long get_phi(long long x)
{
    if (x<=maxn-50) return phi[x];
    if (mp[x]) return mp[x];
    long long ans=(long long)x*(x+1)/2;
    long long l=2,r;
    while (l<=x)
    {
        r=x/(x/l);
        ans-=(long long)(r-l+1)*get_phi(x/l);
        l=r+1;
    }
    return mp[x]=ans;
}
int main()
{
    scanf("%lld",&n);get_table();
    printf("%lld\n",get_phi(n));
    return 0;
}