[bzoj 2440] 完全平方数

题目大意

求从 (1) 开始第 (k) 个不是完全平方数的整倍数的数,多组询问。

(1 leqslant k leqslant 1,000,000,000)

(1 leqslant T leqslant 50)

题目链接

BZOJ 2440

题解

可以用容斥原理计算出小于等于 (n) 的数中有多少个是完全平方数的整倍数,即加上 (frac{n}4)(frac{n}9)(frac{n}{25}) 等质数的平方,再减去 (frac{n}{16})(frac{n}{36}) 等有两个质因数的数的平方……我们发现,它们的系数就是对应数的莫比乌斯函数的定义(的相反数),因此可以直接算出小于等于 (n) 的数中有多少个满足要求: [
sum_{i = 1}^{lfloor sqrt{n} rfloor} mu(i) * frac{n}{i^2}
]
线性筛预处理出莫比乌斯函数即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

const int MAXN = 100005;
int prime[MAXN], mu[MAXN], primeCnt;
bool notPrime[MAXN];
void () {
notPrime[0] = notPrime[1] = true;
mu[1] = 1;
for (int i = 2; i < MAXN; i++) {
if (!notPrime[i]) {
prime[++primeCnt] = i;
mu[i] = -1;
}
for (int j = 1; j <= primeCnt && i * prime[j] < MAXN; j++) {
notPrime[i * prime[j]] = true;
if (i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
} else {
mu[i * prime[j]] = -mu[i];
}
}
}
}
long long check(long long x) {
long long res = 0;
for (long long i = 1; i * i <= x; i++) res += mu[i] * x / i / i;
return res;
}
long long dichotomy(int k) {
long long l = 1, r = (long long) MAXN * MAXN;
while (l < r) {
long long mid = l + (r - l) / 2;
if (check(mid) >= k) r = mid;
else l = mid + 1;
}
return l;
}
int main() {
linearShaker();
int T;
scanf("%d", &T);
while (T--) {
int k;
scanf("%d", &k);
printf("%lldn", dichotomy(k));
}
return 0;
}