其实这道题只是莫比乌斯函数的应用,并没有反演。。。
题目意思就是说找到第k个不是完全平方数正整数倍的数。
找这个数,我们肯定想到了二分答案是不是?对,就是他,此时我们把问题转化为了[1,x]中有几个不是完全平方数正整数倍的数。
然后我们就会想到用容斥去做
+ 0个质因子的倍数(1的倍数)
- 1个质因子平方的倍数(4的倍数,9的倍数,25的倍数。。。)
+2个质因子平方的倍数(36的倍数,100的倍数。。。)
。。。。。。
然后发现和莫比乌斯函数表示的形式是一样的。
然后这题就这样解出来了
1.线性筛出莫比乌斯函数(1,sqrt(2*10^9))听说有人证明了答案一定是小于2n的,本人不才,不会证。。。
2.二分答案ans,然后容斥求有几个数,然后就可以了。
贴代码:
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<cstring>
#define ll long long
using namespace std;
ll T,n;
int prime[100000];
int miu[100000];
bool bo[100000];
void makemiu()
{
memset(bo,true,sizeof(bo));
miu[1]=1;
int tot=0;
for(int i=2;i<=100000;i++)
{
if(bo[i]) prime[++tot]=i,miu[i]=-1;
for(int j=1;j<=tot&&prime[j]*i<=100000;j++)
{
bo[prime[j]*i]=0;
if(i%prime[j]==0)
{
miu[i*prime[j]]=0;
break;
}
miu[i*prime[j]]=-miu[i];
}
}
}
ll pd(ll u)
{
ll ans=0;
int sqr=sqrt(u);
for(int i=1;i<=sqr;i++)
ans+=miu[i]*(u/(i*i));
return ans;
}
ll find(ll n)
{
ll l=1,r=n*2;
while(l<r-1)
{
int mid=l+r>>1;
if(pd(mid)<n)
l=mid;
else
r=mid;
}
return r;
}
int main()
{
scanf("%lld",&T);
makemiu();
while(T--)
{
scanf("%lld",&n);
printf("%lld\n",find(n));
}
return 0;
}