[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; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream