【BZOJ2440】【中山市选2011】—完全平方数(莫比乌斯函数+容斥原理)

传送门

题意:求第kk个无平方因子数

考虑到第kk个不好求
二分一个数xx,计算xx以内的无平方因子数

由于容斥原理
ans=nans=n-质数的平方的所有倍数+2个质数之积的平方的所有倍数-3个质数之积的平方的所有倍数+4个……
这是个简单的容斥很好证明

考虑一下每个的符号,质数为-,2个质数为++,3个质数为-,4个质数为++

就是莫比乌斯函数!!

由于大于n\sqrt n的数的平方已经大于nn了,所以我们只需要枚举n\sqrt n以内的数

而一个数的平方在nn内的出现次数为ni2\lfloor \frac{n}{i^2} \rfloor

所以ans=i=1nμ(i)ni2ans=\sum_{i=1}^{\sqrt n}\mu(i)\lfloor \frac{n}{i^2} \rfloor

整除分块即可

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	char ch=getchar();
	int res=0;
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
	return res;
}
#define ll long long
const int N=100005;
int mu[N],pr[N],vis[N],sum[N],tot,n,k;
inline void init(){
	mu[1]=1;
	for(int i=2;i<N;++i){
		if(!vis[i])pr[++tot]=i,mu[i]=-1;
		for(int j=1;j<=tot&&i*pr[j]<N;++j){
			vis[i*pr[j]]=1;
			if(i%pr[j]==0)break;
			mu[i*pr[j]]=-mu[i];
		}
	}
	for(int i=1;i<N;++i)sum[i]=sum[i-1]+mu[i];
}
inline bool check(int x){
	int p=sqrt(x),ans=0;
	for(int i=1,nxt;i<=p;i=nxt+1){
		nxt=min((int)sqrt(x/(x/(i*i))),p);
		ans+=(x/(i*i))*(sum[nxt]-sum[i-1]);
	}
	return ans>=n;
}
int main(){
	int T=read();init();
	while(T--){
		n=read();int ans=0;
		int l=1,r=n*2;
		while(l<=r){
			int mid=((ll)l+(ll)r)>>1;
			if(check(mid))ans=mid,r=mid-1;
			else l=mid+1;
		}
		cout<<ans<<'\n';
	}
}
posted @ 2019-02-18 16:39  Stargazer_cykoi  阅读(145)  评论(0编辑  收藏  举报