杜教筛

杜教筛

此处为莫比乌斯函数和欧拉函数的

# include <bits/stdc++.h>
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
const int MAXN=5e6;
int v[MAXN+10],p[MAXN+10];
LL mu[MAXN+10],phi[MAXN+10];
inline void init()
{
v[1]=mu[1]=phi[1]=1;
int cnt=0;
for(int i=2;i<=MAXN;i++){
if(!v[i]) p[++cnt]=i,mu[i]=-1,phi[i]=i-1;
for(int j=1;j<=cnt&&i*p[j]<=MAXN;j++){
v[i*p[j]]=1;
if(i%p[j]) mu[i*p[j]]=-mu[i],phi[i*p[j]]=phi[i]*phi[p[j]];
else { mu[i*p[j]]=0,phi[i*p[j]]=phi[i]*p[j]; break; }
}
}
for(int i=1;i<=MAXN;i++) mu[i]+=mu[i-1],phi[i]+=phi[i-1];
}
unordered_map<int,LL> ansmu,ansphi;
inline LL S_phi(int n)
{
if(n<=MAXN) return phi[n];
if(ansphi[n]) return ansphi[n];
LL ans=0;
for(int l=2,r;r<2147483647&&l<=n;l=r+1)//特判
r=n/(n/l),ans+=(r-l+1)*S_phi(n/l);
return ansphi[n]=(ULL)n*(n+1ll)/2ll-ans;//转ULL避免溢出
}
inline LL S_mu(int n)
{
if(n<=MAXN) return mu[n];
if(ansmu[n]) return ansmu[n];
LL ans=0;
for(int l=2,r;r<2147483647&&l<=n;l=r+1)//同上
r=n/(n/l),ans+=(r-l+1)*S_mu(n/l);
return ansmu[n]=1ll-ans;
}
int main()
{
init();
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
printf("%lld %lld\n",S_phi(n),S_mu(n));
}

return 0;
}

 

 

posted @ 2022-02-26 23:13  fengzlj  阅读(69)  评论(0)    收藏  举报