首先我们可以二分答案。然后转变为判断 (mid) 以内不讨厌的数和 (k) 的关系。
(mid) 以内不讨厌的数= (mid) (-) (mid) 以内讨厌的数
对于讨厌的数我们可以枚举 (i),看 (i^2) 会造成多少个讨厌的数,显然是 (displaystyle left lfloor frac{n}{i^2} ight floor)
然后我们发现会有重复枚举的(像 (36) 会被 (2,3,6) 都枚举到),需要乘上一个容斥系数 (f[i]).
(f[i]) 取决于 (i) 有多少个质因数,奇数个为 (1) ,偶数个为 (-1) 。
这很好理解,比如一个数 (n) ,会被有一个质因数的 (i) 枚举的时候加上,被有偶数个质因数的 (i) 枚举的时候会发现减多了,枚举有 (3) 个质因数的 (i) 时还得加回来...
#include<iostream>
#include<cstdio>
#define LL long long
using namespace std;
int T, tot;
LL n, k, ans, l, r, mid;
int zhi[100010], f[100010], vis[100010];
void YYCH()
{
for (int i = 2; i <= 100000; ++i)
{
if (!vis[i])zhi[++tot] = i;
for (int j = 1; j <= tot && i * zhi[j] <= 100000; ++j)
{
vis[i * zhi[j]] = 1;
if (!(i % zhi[j]))break;
}
}
}
void dfs(int x, int beg, int js)
{
f[x] = js & 1 ? 1 : -1; long long y;
for (int i = beg; i <= tot; ++i)
{
if ((y = (long long)x * zhi[i]) > 100000)break;
dfs(y, i + 1, js + 1);
}
}
int check(LL n)
{
LL res = 0;
for (int i = 2; (LL)i * i <= n; ++i)
if (f[i])res += f[i] * n / ((LL)i * i);
return n - res;
}
signed main()
{
YYCH(); dfs(1, 1, 0);
cin >> T;
while (T--)
{
scanf("%lld", &k); l = 1; r = k << 1;
while (l <= r)
{
mid = (l + r) >> 1;
if (check(mid) >= k)r = mid - 1, ans = mid;
else l = mid + 1;
}
printf("%lld
", ans);
}
return 0;
}