数学:杜教筛
Luogu4213:杜教筛求积性函数的前n项和
这里的模板是求欧拉函数和莫比乌斯函数前n项和的,如果对于复杂的,需要狄利克雷卷积来推式子
用完全积性函数去拼凑
1 #include<cstdio> 2 #include<unordered_map> 3 #include<iostream> 4 using namespace std; 5 const int maxn=5000005; 6 int n,cnt; 7 bool vis[maxn]; 8 int mu[maxn],summu[maxn],prim[maxn]; 9 long long phi[maxn],sumphi[maxn]; 10 unordered_map<int,int> mpmu; 11 unordered_map<long long,long long> mpphi; 12 inline long long read() 13 { 14 long long x=0,f=1;char ch=getchar(); 15 while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();} 16 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 17 return x*f; 18 } 19 void sieve(int x) 20 { 21 phi[1]=mu[1]=1; 22 for(int i=2;i<=x;i++) 23 { 24 if(!vis[i]) 25 { 26 prim[++cnt]=i; 27 mu[i]=-1;phi[i]=i-1; 28 } 29 for(int j=1;j<=cnt&&prim[j]*i<=x;j++) 30 { 31 vis[i*prim[j]]=1; 32 if(i%prim[j]==0) 33 { 34 phi[i*prim[j]]=phi[i]*prim[j]; 35 break; 36 } 37 else 38 { 39 mu[i*prim[j]]=-mu[i]; 40 phi[i*prim[j]]=phi[i]*(prim[j]-1); 41 } 42 } 43 } 44 for(int i=1;i<=x;i++) 45 { 46 summu[i]=summu[i-1]+mu[i]; 47 sumphi[i]=sumphi[i-1]+phi[i]; 48 } 49 } 50 int djsmu(int x) 51 { 52 if(x<=5000000) return summu[x]; 53 if(mpmu[x]) return mpmu[x]; 54 int ans=1; 55 for(int l=2,r;l<=x;l=r+1) 56 { 57 r=x/(x/l); 58 ans-=(r-l+1)*djsmu(x/l); 59 } 60 return mpmu[x]=ans; 61 } 62 long long djsphi(long long x) 63 { 64 if(x<=5000000) return sumphi[x]; 65 if(mpphi[x]) return mpphi[x]; 66 long long ans=x*(x+1)/2; 67 for(long long l=2,r;l<=x;l=r+1) 68 { 69 r=x/(x/l); 70 ans-=(r-l+1)*djsphi(x/l); 71 } 72 return mpphi[x]=ans; 73 } 74 int main() 75 { 76 int T; 77 T=read(); 78 sieve(5000000); 79 while(T--) 80 { 81 n=read(); 82 printf("%lld %d\n",djsphi(n),djsmu(n)); 83 } 84 return 0; 85 }
不开O2过不了