模板杜教筛
Posted hsez-cyx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板杜教筛相关的知识,希望对你有一定的参考价值。
仅有模板,不含讲解,推荐讲解
Description
题目描述
给定一个正整数N(N≤2^31−1)
求
$$ans_1=sum_{i=1}^nvarphi(i)$$
$$ans_2=sum_{i=1}^n mu(i)$$
输入格式
一共T+1行 第1行为数据组数T(T<=10) 第2~T+1行每行一个非负整数N,代表一组询问
输出格式
一共T行,每行两个用空格分隔的数ans1,ans2
Code
#include <cstdio> #include <cstdlib> #include <map> #define ll long long using namespace std; const int N=6e6,M=6e6+10; ll phi[M]; int prime[M],tot,vis[M],T,n,u[M]; map <ll,ll> wp; map <int,int> wu; inline char get() { static char buf[1024]; static int pos=0,size=0; if(pos==size) { size=fread(buf,1,1024,stdin); pos=0; if(!size) return EOF; else return buf[pos++]; } else return buf[pos++]; } int read() { int sum=0,fh=1; char ch=get(); while(!(ch>=‘0‘ && ch<=‘9‘)) { if(ch==‘-‘) fh=-1; ch=get(); } while(ch>=‘0‘ && ch<=‘9‘ && ch!=EOF) sum=sum*10+ch-48,ch=get(); return sum*fh; } void init() { phi[1]=u[1]=1; for(int i=2;i<=N;i++) { if(!vis[i]) phi[i]=i-1,prime[++tot]=i,u[i]=-1; for(int j=1;j<=tot && prime[j]<=N/i;j++) { int x=prime[j]*i; vis[x]=1; if(i%prime[j]==0) { phi[x]=phi[i]*prime[j]; break; } else u[x]=-u[i],phi[x]=phi[i]*(prime[j]-1); } u[i]+=u[i-1],phi[i]+=phi[i-1]; } } int getu(int x) { if(x<=N) return u[x]; if(wu[x]) return wu[x]; int ans=1; for(int l=2,r;l<=x;l=r+1) { r=x/(x/l); ans-=(r-l+1)*getu(x/l); } return wu[x]=ans; } ll getphi(ll x) { if(x<=N) return phi[x]; if(wp[x]) return wp[x]; ll ans=x*(x+1)/2; for(ll l=2,r;l<=x;l=r+1) { r=x/(x/l); ans-=(r-l+1)*getphi(x/l); } return wp[x]=ans; } int main() { init(); T=read(); while(T--) { n=read(); printf("%lld %d ",getphi(n),getu(n)); } return 0; }
以上是关于模板杜教筛的主要内容,如果未能解决你的问题,请参考以下文章