杜教筛模版
1 #include<bits/stdc++.h> 2 #include<ext/pb_ds/assoc_container.hpp> 3 using namespace __gnu_pbds; 4 using namespace std; 5 int n,m,T,ans; 6 const int MAXN=7000000; 7 vector<int>prime; 8 bool check[MAXN+5]; 9 short mob[MAXN+5],premob[MAXN+5]; 10 int phi[MAXN+5]; 11 long long prephi[MAXN+5]; 12 void sieve() 13 { 14 prephi[1]=phi[1]=1; //欧拉筛 15 premob[1]=mob[1]=1; //莫比乌斯函数筛 16 for(int i=2;i<=MAXN;i++) 17 { 18 if(check[i]==0) 19 { 20 prime.push_back(i); 21 phi[i]=i-1; 22 mob[i]=-1; 23 } 24 for(int j=0;j<prime.size()&&i*prime[j]<=MAXN;j++) 25 { 26 check[i*prime[j]]=1; 27 if(i%prime[j]==0) 28 { 29 phi[i*prime[j]]=phi[i]*prime[j]; 30 mob[i*prime[j]]=0; 31 break; 32 } 33 phi[i*prime[j]]=phi[i]*(prime[j]-1); 34 mob[i*prime[j]]=-mob[i]; 35 } 36 prephi[i]=prephi[i-1]+phi[i]; 37 premob[i]=premob[i-1]+mob[i]; 38 } 39 } 40 struct DuSieve 41 { 42 function<long long(int)>get_preFcovG,get_preG,get_preF; 43 gp_hash_table<int,long long>F; 44 long long get_preF(int n) 45 { 46 if(n<=MAXN)return get_preF(n); 47 if(F.find(n)!=F.end())return F[n]; 48 long long ans=get_preFcovG(n); 49 for(long long l=2,r;l<=n;l=r+1) 50 { 51 r=n/(n/l); 52 ans-=(get_preG(r)-get_preG(l-1))*get_preF(n/l); 53 } 54 return F[n]=ans; 55 } 56 DuSieve(function<long long(int)>FcG,function<long long(int)>pG,function<long long(int)>pF) 57 { 58 get_preFcovG=FcG; 59 get_preG=pG; 60 get_preF=pF; 61 } 62 }; 63 int main() 64 { 65 sieve(); 66 DuSieve PHI=DuSieve([](int n) {return (1ll+n)*n/2;},[](int n) {return n;},[](int n) {return prephi[n];}); 67 DuSieve MU=DuSieve([](int n) {return 1;},[](int n) {return n;},[](int n) {return premob[n];}); 68 scanf("%d",&T); 69 while(T--) 70 { 71 scanf("%d",&n); 72 printf("%lld %lld\n",PHI.get_preF(n),MU.get_preF(n)); 73 } 74 return 0; 75 }