[BZOJ4805]欧拉函数求和
2018-02-26 14:40
399 查看
题目大意:
对于给定的$n(n\leq2\times10^9)$,求$\sum_{i=1}^n\varphi(i)$。
思路:
设$S(n)=\sum_{i=1}^n\varphi(i)$。
因为$\sum_{d|n}\varphi(d)=n$,$S(n)=\sum_{i=1}^n(i-\sum_{d|i,d<i}\varphi(d))=\frac{n(n+1)}2-\sum_{i=2}^nS(\lfloor\frac ni\rfloor)$。
#include<cmath> #include<cstdio> #include<cctype> #include<hash_map> typedef long long int64; inline int getint() { register char ch; while(!isdigit(ch=getchar())); register int x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x; } const int N=1587402,M=120256; bool vis ; int lim,phi ,p[M]; int64 sum ; __gnu_cxx::hash_map<int,int64> map; inline void sieve() { sum[1]=phi[1]=1; for(register int i=2;i<=lim;i++) { if(!vis[i]) { p[++p[0]]=i; phi[i]=i-1; } for(register int j=1;j<=p[0]&&i*p[j]<=lim;j++) { vis[i*p[j]]=true; if(i%p[j]==0) { phi[i*p[j]]=phi[i]*p[j]; break; } phi[i*p[j]]=phi[i]*phi[p[j]]; } sum[i]=sum[i-1]+phi[i]; } } inline int64 calc(const int &n) { if(n<=lim) return sum ; if(map.count(n)) return map ; int64 ans=(int64)n*(n+1)/2; for(int l=2,r;l<=n;l=r+1) { r=n/(n/l); ans-=calc(n/l)*(r-l+1); } return map =ans; } int main() { const int n=getint(); lim=pow(n,2./3); sieve(); printf("%lld\n",calc(n)); return 0; }
线性筛预处理$S$的前$n^{\frac23}$项,剩下的数论分块计算,用哈希表保存已经算过的值,记忆化搜索即可。时间复杂度$O(n^{\frac23})$。
相关文章推荐
- bzoj 4805 欧拉函数求和 杜教筛
- 【BZOJ3944/4805】Sum/欧拉函数求和 杜教筛
- bzoj 4805: 欧拉函数求和
- BZOJ4805: 欧拉函数求和(杜教筛)
- [BZOJ]4805: 欧拉函数求和
- bzoj4805: 欧拉函数求和
- BZOJ 4805 欧拉函数求和 数论
- BZOJ 4805(欧拉函数求和-杜教筛)
- bzoj 4805: 欧拉函数求和 杜教筛
- BZOJ 4805 欧拉函数求和
- BZOJ4805 - 欧拉函数求和
- 【BZOJ4805】欧拉函数求和(杜教筛)
- 【BZOJ4805】欧拉函数求和(杜教筛)
- Bzoj4805: 欧拉函数求和
- bzoj 2818 Gcd 欧拉函数求和
- HYSBZ 4805 欧拉函数求和
- bzoj4802 欧拉函数(附Millar-Rabin和Pollard-Rho讲解)
- bzoj 1409 Password 矩阵快速幂+欧拉函数
- Bzoj4805: 欧拉函数求和
- BZOJ 仪仗队 (线性筛欧拉函数)