题目链接:bzoj2440
题意:
小X讨厌所有是完全平方数的正整数倍的数。你要选第 K个小X不讨厌的数送给了小X。问这个数是多少。
题解:
二分+容斥原理+莫比乌斯函数
中山市选怎么辣么神..//还好不是那年的
小X讨厌的数x就是有某个质因子的指数≥2的数,于是就想到了
μ(x)=0
。
那么要计算它不讨厌的数的话,假设这个数为ans。
那么就要求
ans−ans22−ans32−…+ans(2×3)2+…=K
就是利用容斥原理,把是完全平方数的正整数倍的数减掉,让剩下的数的个数恰为
K
。
于是观察一下上面那个式子,再联想
所以就二分答案通过这个来验证就好了。
//不要问我为什么二分的上限是
2k
我也不知道
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
#define maxn 51000
bool ispri[maxn];
LL mu[maxn],pri[maxn],cnt;
void mobius(LL lim)
{
cnt=0;mu[1]=1;
for (LL i=2;i<=lim;i++)
{
if (!ispri[i]) {pri[++cnt]=i;mu[i]=-1;}
for (LL j=1;j<=cnt && pri[j]*i<=lim;j++)
{
ispri[i*pri[j]]=true;
if (i%pri[j]==0)
{
mu[i*pri[j]]=0;
break;
}
mu[i*pri[j]]=-mu[i];
}
}
}
LL check(LL x)
{
LL m=(LL)sqrt(x);
LL ret=0;
for (LL i=1;i<=m;i++)
ret+=mu[i]*(x/(i*i));
return ret;
}
int main()
{
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
LL T,k,l,r,mid,ret;
scanf("%lld",&T);
mobius(50000);
while (T--)
{
scanf("%lld",&k);
l=k;r=2*k;
while (l<=r)
{
mid=(l+r)>>1;
if (check(mid)>=k) ret=mid,r=mid-1;
else l=mid+1;
}
printf("%lld\n",ret);
}
return 0;
}