[中山市选2011]完全平方数[BZOJ2440]

版权声明:作为一个蒟蒻,转载时请通知我这个蒟蒻 https://blog.csdn.net/zyszlb2003/article/details/89707205

题面描述

传送门

思路

很明显地,一个数不属于完全平方数或完全平方数的倍数,它的 μ \mu 一定不等于0.

因此我们只要二分枚举 x x

计算 [ 1 , x ] [1,x] 之中的非完全平方数

根据容斥原理: x x 以内非完全平凡数的个数为:

x x - [ 1 , x ] [1,x] 中一个质数( 2 , 3 , 5 , . . . 2,3,5,... )的平方的倍数的数量+ [ 1 , x ] [1,x] 中两个质数之积( 6 , 10 , 14 , . . . 6,10,14,... )的平方的倍数的数量-…

所以我们可以枚举 i [ 1 , x \forall i\in[1,\left\lfloor\\ \sqrt{x}\right\rfloor μ ( i ) \mu(i) 是否等于0,就说明它是否是一个完全平方数。若 = 0 =0 ,则是。

a n s = i = 1 x μ ( i ) x / ( i i ) ans=\sum\limits_{i=1}^{\left\lfloor\\ \sqrt{x}\right\rfloor}\mu(i)*\left\lfloor\\ x/(i*i)\right\rfloor 恰好就是非完全平方数的个数。

二分判断即可。

AC code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#define ll long long
#define gc getchar()
using namespace std;
const int N=5e4+10;
const int M=3e4+10;
const int inf=5e4;
inline void qr(ll &x)
{
	x=0;int f=1;char c=gc;
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
	while(c>='0'&&c<='9'){x=(x*10)+(c^48);c=gc;}
	x*=f;
}
int prime[M],m,mu[N];bool v[N];
inline void g_p()
{
	m=0;memset(v,false,sizeof(v));mu[1]=1;
	for(int i=2;i<=inf;i++)
	{
		if(!v[i])prime[++m]=i,mu[i]=-1;
		for(int j=1;j<=m&&i*prime[j]<=inf;j++)
		{
			v[i*prime[j]]=1;
			if(i%prime[j]==0){mu[i*prime[j]]=0;break;}
			mu[i*prime[j]]=-mu[i];
		}
	}
}
ll k;
ll calc(ll x)
{
	int t=sqrt(x);ll ans=0;
	for(ll i=1;i<=t;i++)
		ans+=mu[i]*(x/(i*i));//容斥 
	return ans;
}
int main()
{
	g_p();
	ll t;qr(t);
	while(t--)
	{
		qr(k);
		ll l=0,r=1644934081;
		while(l<r)
		{
			ll mid=(l+r)>>1;//配套 
			if(calc(mid)>=k)r=mid;
			else l=mid+1;
		}
		printf("%lld\n",l);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zyszlb2003/article/details/89707205