思路:
对于每一个数x,我们需要二分答案位置p考虑 [1,p] 有多少满足条件的数,如果这个数等于x,那么说明我们二分的答案p可能是答案(如果p正好是一个完全平方数或完全平方数的整数倍,那么这个p就不是答案,我们需要接着二分)
然后是统计区间
[1,p]
里满足条件的数的个数的方法。
首先我们先假设这个区间里都是满足条件的,那么有res = p个。
然后我们从i=2开始枚举小于
sqrt(p)
的数作为除数。
区间里凡是有
i2
的,有一个减一个,所以直接用p除以
i2
我们就能知道这p个数里面有几个是
i2
的倍数的了。
然后i=3,同样这么处理。
直到
i∗i>p
然而这么处理我们发现有问题,当i=6时算出来的36 早就被i=2和i=3时算过了,所以这里我们要加上i=6的。
而莫比乌斯函数正好满足这样的性质,所以用莫比乌斯实现容斥定理。
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define eps 1e-8
typedef long long int lli;
using namespace std;
const int maxn = 1e6+10;
bool isprime[maxn];
lli prime[maxn],miu[maxn];
void moblus(){
int cnt = 0;miu[1] = 1;
for(lli i = 2;i < maxn;i++){
if(!isprime[i]){
prime[cnt++] = i; miu[i] = -1;
}
for(lli j = 0;j < cnt && i*prime[j] < maxn;j++){
isprime[i*prime[j]] = 1;
if(i%prime[j])
miu[i*prime[j]] = -miu[i];
else{
miu[i*prime[j]] = 0; break;
}
}
}
}
lli jud(lli x){
lli len = sqrt(x);lli res = 0;
for(lli i = 1;i <= len;i++){
res += miu[i]*(x/(i*i));
}
return res;
}
int main(){
lli t;
scanf("%lld",&t);
moblus();
while(t--){
lli n;
scanf("%lld",&n);
lli l = 1,r = (n<<1),mid,ans;
while(l <= r){
mid = (l+r)/2;
lli ju = jud(mid);
if(ju >= n){
ans = mid;
r = mid-1;
}
else if(ju < n){
l = mid+1;
}
}
printf("%lld\n",ans);
}
return 0;
}