题目即要求第k个不含平方因子的数,即每个质数的次数都为1。
那么我们可以二分答案,然后求出在[1,mid]间的无平方因子数的个数。
考虑容斥原理,无平方因子数的个数=总个数-含一个质数平方的个数+含两个质数平方的个数……
可以发现每一项前的系数恰为μ(i),所以个数就为∑m√idi=1μ(i)×⌊midi2⌋,然后就好啦。
二分过程不要忘记开long long
#include<iostream>
#include<cstdio>
#define MAXN 44723
#define ll long long
using namespace std;
int mobius[MAXN],prime[MAXN];
bool flag[MAXN];
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
inline void prepare()
{
mobius[1]=1;
for (int i=2;i<MAXN;i++)
{
if (!flag[i]) prime[++prime[0]]=i,mobius[i]=-1;
for (int j=1;j<=prime[0]&&i*prime[j]<MAXN;j++)
{
flag[i*prime[j]]=1;
if (i%prime[j]==0)
{
mobius[i*prime[j]]=0;
break;
}
mobius[i*prime[j]]=-mobius[i];
}
}
}
inline int judge(int x)
{
int tmp=0;
for (int i=1;i*i<=x;i++)
tmp+=x/(i*i)*mobius[i];
return tmp;
}
inline ll find(int k)
{
ll l=1,r=k<<1,ans;
while (l<=r)
{
ll mid=l+r>>1;
if (judge(mid)>=k) ans=mid,r=mid-1; else l=mid+1;
}
return ans;
}
int main()
{
prepare();
int testcase=read();
while (testcase--)
{
int k=read();
printf("%lld\n",find(k));
}
return 0;
}