BZOJ 3944 Sum
题目链接:Sum
嗯……不要在意……我发这篇博客只是为了保存一下杜教筛的板子的……
你说你不会杜教筛?唐老师(其实我不认识)写了一篇讲的非常好的博客,看完应该就会了……
这道题就是杜教筛板子题,也没什么好讲的……
下面贴代码(不知道为什么我的常数就是大):
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) #define maxn 5664511 using namespace std; typedef long long llg; int pr[maxn],T,n,lp; bool vis[maxn],vu[1300],vp[1300]; llg mu[maxn],phi[maxn],su[1300],sp[1300]; void pre(){ mu[1]=phi[1]=1; for(int i=2;i<maxn;i++){ if(!vis[i]) pr[++lp]=i,mu[i]=-1,phi[i]=i-1; for(int j=1;j<=lp && pr[j]*i<maxn;j++){ vis[i*pr[j]]=1; if(i%pr[j]!=0) mu[i*pr[j]]=-mu[i],phi[i*pr[j]]=phi[i]*phi[pr[j]]; else{phi[i*pr[j]]=phi[i]*pr[j];break;} } } for(int i=2;i<maxn;i++) mu[i]+=mu[i-1],phi[i]+=phi[i-1]; } llg solveu(int x){ if(x<maxn) return mu[x]; if(vu[n/x]) return su[n/x]; llg now=1; vu[n/x]=1; for(int i=2,nt=0;nt<x;i=nt+1) nt=x/(x/i),now-=(nt-i+1)*solveu(x/i); return su[n/x]=now; } llg solvep(llg x){ if(x<maxn) return phi[x]; if(vp[n/x]) return sp[n/x]; llg now=x*(llg)(x+1); now>>=1; for(int i=2,nt=0;nt<x;i=nt+1) nt=x/(x/i),now-=(nt-i+1)*solvep(x/i); vp[n/x]=1; return sp[n/x]=now; } int main(){ File("a"); scanf("%d",&T); pre(); while(T--){ scanf("%d",&n); memset(vu,0,sizeof(vu)); memset(vp,0,sizeof(vp)); printf("%lld %lld\n",solvep(n),solveu(n)); } return 0; }