思路:
杜教筛裸题
//By SiriusRen
#include <map>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=5000050;
typedef long long ll;
int prime[N],vis[N],mu[N],maxx=5000000,tot,n,cases;
ll phi[N];
map<int,ll>_phi,_mu;
map<int,ll>::iterator it;
void shai(){
mu[1]=phi[1]=1;
for(int i=2;i<=maxx;i++){
if(!vis[i])prime[++tot]=i,mu[i]=-1,phi[i]=i-1;
for(int j=1;j<=tot&&i*prime[j]<=maxx;j++){
vis[i*prime[j]]=1,mu[i*prime[j]]=-mu[i],phi[i*prime[j]]=phi[i]*(prime[j]-1);
if(i%prime[j]==0){
mu[i*prime[j]]=0,phi[i*prime[j]]=phi[i]*prime[j];
break;
}
}
mu[i]+=mu[i-1],phi[i]+=phi[i-1];
}
}
ll get_phi(ll x){
if(x<=maxx)return phi[x];
if((it=_phi.find(x))!=_phi.end())return it->second;
ll re=1ll*x*(x+1)/2;
for(ll i=2,last;i<=x;i=last+1){
last=x/(x/i);
re-=(last-i+1)*get_phi(x/i);
}return _phi[x]=re;
}
int get_mu(ll x){
if(x<=maxx)return mu[x];
if((it=_mu.find(x))!=_mu.end())return it->second;
int re=1;
for(ll i=2,last;i<=x;i=last+1){
last=x/(x/i);
re-=(last-i+1)*get_mu(x/i);
}return _mu[x]=re;
}
signed main(){
shai();
scanf("%d",&cases);
while(cases--){
scanf("%d",&n);
printf("%lld %d
",get_phi(n),get_mu(n));
}
}