[51nod1239欧拉函数之和]

来自FallDream的博客,未经允许,请勿转载,谢谢

---------------------------------------------

给定n,求$S(n)=\sum_{i=1}^{n}\varphi(i)$  n<=$10^{10}$ 

跟求莫比乌斯函数前缀和一样的做法,也可以推出$S(n)=\frac{n*(n+1)}{2}-\sum_{i=2}^{n}S(i)$,具体推法可以戳这里

另外,我们还可以从gcd入手。

数对$\left(x,y\right),x\leqslant y$共有$\frac{n*(n+1)}{2}$种,那么$S(n)=\sum1\left(gcd(x,y)=1, x\leqslant y\leqslant n\right)) $

又$num\left(gcd(x,y)=c\right)$的有$S(\lfloor n/c\rfloor)$种,所以$S(n)=\frac{n*(n+1)}{2}-\sum_{i=2}^{n}S(i)$

虽然推法不同,但是结果是一样的,然后记忆化搜索,复杂度$O(n^{\frac{2}{3}})$  用一个手写map加速,又是轻松rank1

然后latex真好用!!!!!

#include<iostream>
#include<cstdio>
#include<cmath>
#define MAXN 5000000
#define mod 2333333
#define ditoly 1000000007
#define ll long long
using namespace std;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}

struct my_map{
    ll x,ans;int next;
}e[mod+5];
int head[mod+5],num=0;
void ins(ll x,ll sum)
{
    int j=x%mod;
    e[++num]=(my_map){x,sum,head[j]};
    head[j]=num;
}

int phi[MAXN+5];
ll ans=0;

ll calc(ll n)
{
    if(n<=MAXN) return phi[n];
    for(int i=head[n%mod];i;i=e[i].next)
        if(e[i].x==n)return e[i].ans;
    ll sum=(n%ditoly)*((n+1)%ditoly)%ditoly*500000004%ditoly;
    int q=sqrt(n);
    for(int i=2;i<=q;i++)
        sum=(sum-calc(n/i))%ditoly;
    q=n/(q+1);
    for(int i=1;i<=q;i++)
        sum=(sum-((n/i-(n/(i+1)))%ditoly*calc(i))+ditoly)%ditoly;
    ins(n,sum);
    return sum;
}


int main()
{
    for(int i=1;i<=MAXN;i++)phi[i]=i;
    for(int i=2;i<=MAXN;i++)if(phi[i]==i)
    {
        phi[i]=i-1;
        for(int j=i<<1;j<=MAXN;j+=i)
            phi[j]=phi[j]/i*(i-1);
    }num=0;
    for(int i=1;i<=MAXN;i++)phi[i]=(phi[i]+phi[i-1])%ditoly;
    cout<<calc(read())<<endl;
    return 0;
}

 

posted @ 2017-03-25 17:05  FallDream  阅读(648)  评论(0编辑  收藏  举报