杜教筛

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=6e6+50;
unordered_map<int,int>m;
unordered_map<ll,ll>p;
bool vis[maxn];
int mu[maxn],sum_mu[maxn],phi[maxn];
ll sum_phi[maxn];
int cnt,prime[maxn];

void init(int N){
    phi[1]=mu[1]=1;
    for(int i=2;i<=N;i++){
        if(!vis[i]){
            prime[++cnt]=i;
            mu[i]=-1;phi[i]=i-1;
        }
        for(int j=1;j<=cnt;j++){
            if(i*prime[j]>N)break;
            vis[i*prime[j]]=true;
            if(i%prime[j]==0){
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            mu[i*prime[j]]=-mu[i];
            phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
    for(int i=1;i<=N;i++){
        sum_mu[i]=sum_mu[i-1]+mu[i];
        sum_phi[i]=sum_phi[i-1]+phi[i];
    }
}
int getmu(int x){
    if(x<=6e6)return sum_mu[x];
    if(m[x])return m[x];
    int ans=1;
    for(int l=2,r;l<=x;l=r+1){
        r=x/(x/l);
        ans-=(r-l+1)*getmu(x/l);
    }
    return m[x]=ans;
}
ll getphi(ll x){
    if(x<=6e6)return sum_phi[x];
    if(p[x])return p[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 p[x]=ans;
}
int main(){
    int t,n;
    cin>>t;
    init(6e6);
    while(t--){
        cin>>n;
        cout<<getphi(n)<<" "<<getmu(n)<<endl;
    }
	return 0;
}

posted @ 2019-03-26 20:21  luowentao  阅读(141)  评论(0编辑  收藏  举报