题
意
:
题意:
题意:
求
第
k
个
不
含
平
方
因
子
的
数
求第k个不含平方因子的数
求第k个不含平方因子的数
题
解
:
题解:
题解:
我
们
可
以
题
目
转
为
求
给
定
n
,
求
n
以
内
的
无
平
方
因
子
数
的
个
数
,
然
后
二
分
得
到
结
果
\qquad我们可以题目转为求给定n,求n以内的无平方因子数的个数,然后二分得到结果
我们可以题目转为求给定n,求n以内的无平方因子数的个数,然后二分得到结果
求
n
以
内
的
无
平
方
因
子
数
的
个
数
,
即
求
求n以内的无平方因子数的个数,即求
求n以内的无平方因子数的个数,即求
∑
k
=
1
n
μ
2
(
k
)
,
这
里
μ
是
莫
比
乌
斯
函
数
\sum_{k=1}^{n}\mu^{2}(k), 这里\mu是莫比乌斯函数
k=1∑nμ2(k),这里μ是莫比乌斯函数
我 们 考 虑 一 个 素 数 p , 那 么 p 的 倍 数 都 含 有 平 方 因 子 , 个 数 是 ⌊ n p 2 ⌋ , 需 要 从 答 案 中 去 掉 。 但 是 这 样 会 多 去 掉 一 些 数 , 比 如 对 于 不 同 的 素 数 p 1 , p 2 , p 1 2 ⋅ p 2 2 的 倍 数 就 被 去 掉 了 两 次 , 个 数 是 ⌊ n p 1 2 ⋅ p 2 2 ⌋ , 需 要 加 回 来 , 这 里 就 是 使 用 了 容 斥 原 理 . \qquad我们考虑一个素数p, 那么p^的倍数都含有平方因子,个数是 \lfloor \frac{n}{p^2} \rfloor , 需要从答\\ 案中去掉。但是这样会多去掉一些数,比如对于不同的素数p_{1}, p_{2}, \ \ p_{1}^{2} \cdot p_{2}^{2}的\\倍数就被去掉了两次,个数是 \lfloor \frac{n}{p_{1}^{2} \cdot p_{2}^{2}} \rfloor , 需要加回来,这里就是使用了容斥原理. 我们考虑一个素数p,那么p的倍数都含有平方因子,个数是⌊p2n⌋,需要从答案中去掉。但是这样会多去掉一些数,比如对于不同的素数p1,p2, p12⋅p22的倍数就被去掉了两次,个数是⌊p12⋅p22n⌋,需要加回来,这里就是使用了容斥原理.
如 果 d 是 s 个 不 同 素 数 的 乘 积 , 那 么 对 答 案 的 贡 献 就 是 ( − 1 ) s ⌊ n d 2 ⌋ , 如 果 d 含 有 平 方 因 子 , d 对 答 案 没 有 贡 献 , 也 就 是 说 容 斥 的 系 数 就 是 M o b i u s 函 数 \qquad如果d是s个不同素数的乘积, 那么对答案的贡献就是(-1)^s \lfloor \frac{n}{d^2} \rfloor, 如果d含有平方因\\子,d对答案没有贡献,也就是说容斥的系数就是Mobius函数 如果d是s个不同素数的乘积,那么对答案的贡献就是(−1)s⌊d2n⌋,如果d含有平方因子,d对答案没有贡献,也就是说容斥的系数就是Mobius函数
因
此
可
以
有
下
面
的
结
论
,
答
案
就
是
因此可以有下面的结论,答案就是
因此可以有下面的结论,答案就是
∑
k
=
1
n
μ
2
(
k
)
=
∑
d
=
1
n
μ
(
d
)
⌊
n
d
2
⌋
\sum_{k=1}^{n}\mu^{2}(k) = \sum_{d=1}^{\sqrt{n}} \mu(d) \lfloor \frac{n}{d^2} \rfloor
k=1∑nμ2(k)=d=1∑nμ(d)⌊d2n⌋
枚
举
d
,
预
处
理
莫
比
乌
斯
函
数
即
可
\qquad枚举d,预处理莫比乌斯函数即可
枚举d,预处理莫比乌斯函数即可
代
码
:
代码:
代码:
#include <bits/stdc++.h>
using namespace std;
#define Debug(x) cout<<#x<<"="<<x<<endl;
typedef long long LL;
const int N = 100100;
int n, mu[N+50], p[N+50];
int tot;
bool used[N+50];
//预处理出素数 莫比乌斯函数
void init() {
mu[1] = 1;
for (int i = 2; i <= N; i++) {
if (!used[i]) {
mu[i] = -1;
p[++tot] = i;
}
for (int j = 1; j <= tot && p[j] * i <= N; j++) {
used[p[j] * i] = true;
if (i % p[j] == 0) {
mu[i * p[j]] = 0;
break;
}
mu[i * p[j]] = mu[i] * (-1);
}
}
}
LL check(LL n) {
LL res = 0;
for (int i = 1; i * i <= n; i++) {
res += mu[i] * n / (i * i);
}
return res;
}
LL cal(LL k) {
LL l = 1, r = k * 2;
LL ans;
while (l <= r) {
int mid = (l + r) / 2;
int number = check(mid);
if (number >= k) r = mid - 1, ans = mid;
else l = mid + 1;
}
return ans;
}
int main() {
int T;
cin >> T;
init();
while (T--) {
int x;
cin >> x;
cout << cal(x) << endl;
}
return 0;
}