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

传送门

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

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

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

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

就是莫比乌斯函数!!

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

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

所以 a n s = i = 1 n μ ( i ) n i 2 ans=\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';
	}
}

猜你喜欢

转载自blog.csdn.net/qq_42555009/article/details/87628368