题意:找出第k个不是完全平方数的正整数倍的数。
例如 4 9 16 25 36什么的
通过容斥原理,我们减去所有完全数 4有n/4个,但是先36这种会被重复减去,
所有我们还需要加上类似36的数,然后你会发现这些数前面的符号和他们开根号的
莫比乌斯函数一样
数据很大有1e9,如果先进行预处理再从头到尾找感觉不现实,考虑使用二分,枚举mid,
然后每次查找1到mid中不是完全平方数的正整数倍的数的个数
Orz:机制的二分使用
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <vector>
#include <algorithm>
#include <functional>
typedef long long ll;
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 1e5;
int tot;
int is_prime[maxn];
int mu[maxn];
int prime[maxn];
void Moblus()
{
tot = 0;
mu[1] = 1;
for(int i = 2; i < maxn; i++)
{
if(!is_prime[i])
{
prime[tot++] = i;
mu[i] = -1;
}
for(int j = 0; j < tot && i*prime[j] < maxn; j++)
{
is_prime[i*prime[j]] = 1;
if(i % prime[j])
{
mu[i*prime[j]] = -mu[i];
}
else
{
mu[i*prime[j]] = 0;
break;
}
}
}
}
ll get_(ll mid)
{
ll num = 0;
for(int i = 1; i*i <= mid; i++)
{
num += (ll)mu[i]*(mid/(i*i));
}
return num;
}
int main()
{
int T;
Moblus();
scanf("%d",&T);
while(T--)
{
ll k;
scanf("%lld",&k);
ll l = 1;
ll r = 2*k+1;
while(l <= r)
{
ll mid = (l+r)>>1;
ll num = get_(mid);
if(num < k)
l = mid + 1;
else
r = mid - 1;
}
printf("%lld\n",l);
}
}