BZOJ2440 [中山市选2011]完全平方数(莫比乌斯函数+容斥原理+二分答案)

【题解】

本题中完全平方数不考虑1

在1~k*2中二分答案:
对于x,只需求出1~x中有多少个数不是完全平方数的倍数 
由容斥原理:
1~x中 不是完全平方数的倍数 的数的个数 = x - 是至少1个质数n次方的数的个数 + 是至少2个质数n次方的数的个数 - 是至少3个质数n次方的数的个数 …
其中的系数1的正负刚好与 因式中多次出现的质数种类数的奇偶性一致,因此系数可以用类似莫比乌斯函数的方法求得 

而对于每个x,枚举质数只需枚举到sqrt(n)


【代码】

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int no[100005],pri[100005],mu[100005];
int k;
int order(int x)
{
	int sq=(int)sqrt(x+0.5),i,ans=0;
	for(i=1;i<=sq;i++)
		ans+=x/(i*i)*mu[i];
	return ans;
}
int judge(int x)
{
	int sq=(int)sqrt(x+0.5),i;
	for(i=1;pri[i]<=sq;i++)
		if(x%(pri[i]*pri[i])==0) return 0;
	return 1;
}
void erfen(int left,int right)
{
	long long t;
	int mid,ord;
	while(1)
	{
		t=((long long)left+(long long)right)/2LL;
		mid=(int)t;
		ord=order(mid);
		if(ord==k&&judge(mid)==1)
		{
			printf("%d\n",mid);
			return;
		}
		if(ord>=k) right=mid-1;
		else left=mid+1;
	}
}
int main()
{
	int T,i,j,p=0;
	mu[1]=1;//预处理:求莫比乌斯函数 
	for(i=2;i<=100000;i++)
	{
		if(no[i]==0)
		{
			pri[++p]=i;
			mu[i]=-1;
		}
		for(j=1;j<=p&&pri[j]*i<=100000;j++)
		{
			no[pri[j]*i]=1;
			if(i%pri[j]==0) break;
			mu[pri[j]*i]=-mu[i];
		}
	}
	scanf("%d",&T);
	for(;T>0;T--)
	{
		scanf("%d",&k);
		erfen(1,2*k);
	}
    return 0;
}


你可能感兴趣的:(容斥原理,二分答案,莫比乌斯函数)