3944: Sum[杜教筛]
Posted 神犇(shenben)
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3944: Sum[杜教筛]相关的知识,希望对你有一定的参考价值。
3944: Sum
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3471 Solved: 946
[Submit][Status][Discuss]
Description
Input
一共T+1行
第1行为数据组数T(T<=10)
第2~T+1行每行一个非负整数N,代表一组询问
Output
一共T行,每行两个用空格分隔的数ans1,ans2
Sample Input
6
1
2
8
13
30
2333
1
2
8
13
30
2333
Sample Output
1 1
2 0
22 -2
58 -3
278 -3
1655470 2
2 0
22 -2
58 -3
278 -3
1655470 2
HINT
Source
#include<cstdio> #include<cstring> typedef long long ll; typedef unsigned int uint; using namespace std; const int N=5.4e6+5; const int M=1e5+10; ll mu[N],phi[N]; ll ans_mu[M],ans_phi[M]; bool vis_mu[M],vis_phi[M]; int n,m,T;ll ans1,ans2; int tot,prime[N/3];bool check[N]; inline void sieve(){ phi[1]=mu[1]=1; m=N-5; // m=pow(n,2.0/3.0); for(int i=2;i<=m;i++){ if(!check[i]) prime[++tot]=i,mu[i]=-1,phi[i]=i-1; for(int j=1;j<=tot&&i*prime[j]<=m;j++){ check[i*prime[j]]=1; if(!(i%prime[j])){mu[i*prime[j]]=0;phi[i*prime[j]]=phi[i]*prime[j];break;} else mu[i*prime[j]]=-mu[i],phi[i*prime[j]]=phi[i]*(prime[j]-1); } } for(int i=1;i<=m;i++) mu[i]+=mu[i-1],phi[i]+=phi[i-1]; } inline ll get_phi(uint now){ if(now<=m) return phi[now]; int nn=n/now; if(vis_phi[nn]) return ans_phi[nn]; vis_phi[nn]=1; ll sav=(ll)now*(now+1)>>1; for(uint i=2,pos;i<=now;i=pos+1){ pos=now/(now/i); sav-=get_phi(now/i)*(pos-i+1); } return ans_phi[nn]=sav; } inline ll get_mu(uint now){ if(now<=m) return mu[now]; int nn=n/now; if(vis_mu[nn]) return ans_mu[nn]; vis_mu[nn]=1; ll sav=1; for(uint i=2,pos;i<=now;i=pos+1){ pos=now/(now/i); sav-=get_mu(now/i)*(pos-i+1); } return ans_mu[nn]=sav; } inline void clr(){ memset(vis_mu,0,sizeof vis_mu); memset(vis_phi,0,sizeof vis_phi); } int main(){ sieve(); for(scanf("%d",&T);T--;clr()){ scanf("%d",&n); ans1=get_phi(n);ans2=get_mu(n); printf("%lld %lld\n",ans1,ans2); } return 0; }
以上是关于3944: Sum[杜教筛]的主要内容,如果未能解决你的问题,请参考以下文章