Luogu4318 完全平方数

题意:给出 ,求第 小的无平方因子的数。

多组数据,


二分,问题转化为求 以内无平方因子数个数。注意到 ,即求 的前缀和。(注意,此处 而非

。注意到 ,则有 这个结论也可以用容斥原理证明。

代入该式可得 其中 是分段的,且形成 段:

  • 时,每个 单独成段;
  • 时,,至多 段。

为了进行整除分块,需要快速求出连续段的末尾,即对于 求出最大的 满足 。套用之前的结论,满足 的最大的 ,现在要找出最大的 使得 ,即

复杂度

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <cstdio>
#include <cmath>

using ll = long long;
const int MaxN = 50005;

int p[MaxN/5], totP, mu[MaxN];
bool flag[MaxN];

void sieve(int n) {
mu[1] = 1;
for (int i=2; i<=n; i++) {
if (flag[i] == false) {
p[++totP] = i;
mu[i] = -1;
}
for (int j=1; j<=totP; j++) {
int t = i*p[j];
if (t>n) break;
flag[t] = true;
if (i%p[j] == 0) break;
mu[t] = -mu[i];
}
}
for (int i=1; i<=n; i++)
mu[i] += mu[i-1];
}

ll calc(ll n) {
ll ans = 0;
int l = 1;
while(1ll*l*l <= n) {
ll buf = n/(1ll*l*l);
int r = sqrt(n/buf);
ans += buf*(mu[r]-mu[l-1]);
l = r+1;
}
return ans;
}

int main() {
sieve(5e4);

int T;
scanf("%d", &T);

while(T--) {
ll K;
scanf("%lld", &K);
ll l = 1, r = 2*K+100;
while(l<r) {
ll mid = (l+r)>>1;
if (calc(mid)>=K)
r = mid;
else
l = mid+1;
}
printf("%lld\n", r);
}

return 0;
}