BZOJ 3944 Sum

题解:

杜教筛

坑点 n+1会炸int

注意空间

到现在不会unsigned long long的输出

//注意空间 
//注意读入数据2^31-1 
//unsighed long long 输出 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
typedef long long Lint;
typedef unsigned long long uLint;
const int u=5000000;

int TT;
int q[10000];
uLint ans1[100000];
int ans2[100000];

map<int,uLint>ma1;
map<int,int>ma2;

int vis[u+10]={0};
int cntprime=0,prime[u+10];
Lint mu[u+10];
Lint phi[u+10];
void Lineshake(){
	vis[1]=1;mu[1]=1;phi[1]=1;
	for(int i=2;i<=u;++i){
		if(!vis[i]){
			prime[++cntprime]=i;
			mu[i]=-1;
			phi[i]=i-1;
		}
		for(int j=1;(j<=cntprime)&&(i*prime[j]<=u);++j){
			vis[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*prime[j]]=-mu[i];
			phi[i*prime[j]]=phi[i]*(prime[j]-1);
		}
	}
	for(int i=2;i<=u;++i){
		mu[i]+=mu[i-1];
		phi[i]+=phi[i-1];
	}
}

uLint Calphi(int n){
	if(n<=u)return phi[n];
	if(ma1.count(n))return ma1[n];
	uLint ret=((uLint)n)*((uLint)n+1)/2;
	Lint last;
	for(Lint d=2;d<=n;d=last+1){
		last=n/(n/d);
		ret-=(last-d+1)*Calphi(n/d);
	}
	ma1[n]=ret;
	return ret;
}

int Calmu(int n){
	if(n<=u)return mu[n];
	if(ma2.count(n))return ma2[n];
	int ret=1;
	Lint last;
	for(Lint d=2;d<=n;d=last+1){
		last=n/(n/d);
		ret-=(last-d+1)*Calmu(n/d);
	}
	ma2[n]=ret;
	return ret;
}

int main(){
	Lineshake();
	scanf("%d",&TT);
	for(int i=1;i<=TT;++i)scanf("%d",&q[i]);
	
	for(int i=1;i<=TT;++i){
		ans1[i]=Calphi(q[i]);
	}
	
	for(int i=1;i<=TT;++i){
		ans2[i]=Calmu(q[i]);
	}
	for(int i=1;i<=TT;++i){
		cout<<ans1[i]<<' '<<ans2[i]<<endl;
	}
	return 0;
}

  

 

posted @ 2018-03-13 20:17  ws_zzy  阅读(129)  评论(0编辑  收藏  举报