P4213模板杜教筛
Posted shxnb666
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4213模板杜教筛相关的知识,希望对你有一定的参考价值。
题面
https://www.luogu.org/problem/P4213
题解
#include<cstdio> #include<iostream> #include<cstring> #pragma GCC optimize(2) #define ri register int #define maxn 2147483647 #define maxm 3000000 #define maxk 2000 #define LL long long using namespace std; int p[maxm],phi[maxm],miu[maxm],k[maxm],prime[maxm],cnt=0; bool vis[maxm]; LL S1[maxm],S2[maxk]; LL SS1[maxm],SS2[maxk]; bool vis2[maxm]; int T,N; void getS1() phi[1]=1; for (ri i=2;i<maxm;i++) if (p[i]==0) k[i]=p[i]=prime[++cnt]=i; phi[i]=i-1; for (ri j=1;j<=cnt && i*prime[j]<maxm;j++) k[i*prime[j]]=p[i*prime[j]]=prime[j]; phi[i*prime[j]]=phi[i]*phi[prime[j]]; if (prime[j]==p[i]) k[i*prime[j]]*=k[i]; phi[i*prime[j]]=phi[i/k[i]]*phi[prime[j]*k[i]]; if (k[i*prime[j]]==i*prime[j]) phi[i*prime[j]]=i*(prime[j]-1); break; S1[0]=0; for (ri i=1;i<maxm;i++) S1[i]=S1[i-1]+phi[i]; miu[1]=1; for (ri i=2;i<maxm;i++) if (i==p[i]) miu[i]=-1; else if (k[i]==i) miu[i]=0; else miu[i]=miu[i/k[i]]*miu[k[i]]; SS1[0]=0; for (ri i=1;i<maxm;i++) SS1[i]=SS1[i-1]+miu[i]; LL S(int n) if (n<maxm) return S1[n]; ri x=N/n; if (x<maxk && vis[x]) return S2[x]; vis[x]=true; LL &ans=S2[x]; ans=(LL)n*(n+1)/2; for (ri i=2,j;i<=n;i=j+1) j=n/(n/i); ans-=(j-i+1)*S(n/i); return ans; LL SS(int n) if (n<maxm) return SS1[n]; ri x=N/n; if (x<maxk && vis2[x]) return SS2[x]; vis2[x]=true; LL &ans=SS2[x]; ans=(LL)1; for (ri i=2,j;i<=n;i=j+1) j=n/(n/i); ans-=(j-i+1)*SS(n/i); return ans; int main() scanf("%d",&T); getS1(); for (ri i=1;i<=T;i++) scanf("%d",&N); memset(vis,0,sizeof(vis)); memset(vis2,0,sizeof(vis2)); printf("%lld %lld\n",S(N),SS(N));
以上是关于P4213模板杜教筛的主要内容,如果未能解决你的问题,请参考以下文章