P4213 【模板】杜教筛

题面:https://www.luogu.org/problem/P4213

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<ctime>
#include<queue>
#include<map>
using namespace std;
const int mod=1000000007,N=5000005;
long long phi[N];
int t,prime[N],cnt,mobius[N];
bool vis[N];
unordered_map<int,int>ans_mobius;
unordered_map<int,long long> ans_phi;
inline int read(){
    int x=0,f=1;
	char c=getchar();
    while(c<'0'||c>'9'){
		if(c=='-'){
			f=-1;
			c=getchar();
		}
	}
    while(c>='0'&&c<='9'){
		x=x*10+c-48;
		c=getchar();
	}
    return x*f;
}
inline long long get_phi(long long x){
    if(x<=N){
		return phi[x];
	}
    if(ans_phi[x]){
		return ans_phi[x];
	}
    long long ans=((1+x)*x)/2;
    for(register int l=2,r;l<=x;l=r+1){
        r=x/(x/l);
        ans-=(r-l+1)*get_phi(x/l);
    }
    return ans_phi[x]=ans;
}
inline int get_mobius(int x){
    if(x<=N){
		return mobius[x];
	}
    if(ans_mobius[x]){
		return ans_mobius[x];
	}
    int ans=1;
    for(register int l=2,r;l<=x;l=r+1){
        r=x/(x/l);
        ans-=(r-l+1)*get_mobius(x/l);
    }
    return ans_mobius[x]=ans;
}
int main(){
	mobius[1]=phi[1]=1;
    for(register int i=2;i<=N;++i){
        if(!vis[i]){
			prime[++cnt]=i;
			mobius[i]=-1;
			phi[i]=i-1;
		}
        for(register int j=1;j<=cnt&&prime[j]*i<=N;++j){
            vis[prime[j]*i]=1;
            if(i%prime[j]==0){
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            phi[i*prime[j]]=phi[prime[j]]*phi[i];
            mobius[i*prime[j]]=-mobius[i];
        }
    }
    for(register int i=1;i<=N;++i){
		mobius[i]+=mobius[i-1];
		phi[i]+=phi[i-1];
	}
	int x;
    t=read();
    while(t--){
		x=read();
        printf("%lld %d\n",get_phi(x),get_mobius(x));
    }
    return 0;
}
posted @ 2019-08-06 19:27  prestige  阅读(110)  评论(0编辑  收藏  举报