bzoj2440 [中山市选2011]完全平方数
求第 \(k\) 个不是完全平方数的正整数倍的数,\(T\) 组询问
\(T\leq50,\ k\leq10^9\)
容斥+莫比乌斯函数
首先二分答案,将原问题转化为
求 \([1,\ n]\) 中不是完全平方数的正整数倍的数的个数
即 SP4168 SQFREE - Square-free integers
现在考虑原问题的逆问题,即 \([1,\ n]\) 中是完全平方数的正整数倍的数的个数,由容斥原理得到 $$\lfloor\frac{n}{22}\rfloor+\lfloor\frac{n}{32}\rfloor+\lfloor\frac{n}{52}\rfloor-\lfloor\frac{n}{62}\rfloor+\lfloor\frac{n}{72}\rfloor-\lfloor\frac{n}{102}\rfloor+\cdots$$
\(\therefore\) 原式 \(=\) $$n-\lfloor\frac{n}{22}\rfloor-\lfloor\frac{n}{32}\rfloor-\lfloor\frac{n}{52}\rfloor+\lfloor\frac{n}{62}\rfloor-\lfloor\frac{n}{72}\rfloor+\lfloor\frac{n}{102}\rfloor+\cdots$$
现在观察 \(\lfloor\frac{n}{i^2}\rfloor\) 的系数:$$1\times n+(-1)\times\lfloor\frac{n}{22}\rfloor+(-1)\times\lfloor\frac{n}{32}\rfloor+0\times\lfloor\frac{n}{42}\rfloor+(-1)\times\lfloor\frac{n}{52}\rfloor+1\times\lfloor\frac{n}{62}\rfloor+(-1)\times\lfloor\frac{n}{72}\rfloor+0\times\lfloor\frac{n}{8^2}\rfloor+\cdots$$
有没有想到那个熟悉的函数 $$\mu(i)=\begin{cases}1&&(i=1)\(-1)^k&&(i=\prod p_k,\ p_k\in prime)\0&&other\end{cases}$$
易证原式 \(\lfloor\frac{n}{i^2}\rfloor\) 的系数即为 \(\mu(i)\)
即求 $$\displaystyle\sum_{i=1}^\sqrt n \mu(i)\lfloor\frac{n}{i^2}\rfloor$$
可以发现最终答案 \(ans\) 满足 \(k\le ans\leq 2\times k\)
因此时间复杂度 \(O(T\sqrt k\log k)\),空间复杂度 \(O(\sqrt k)\)
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e4 + 10;
int T, n, tot, p[maxn], mu[maxn];
void sieve() {
int t = 45000; mu[1] = 1;
for (int i = 2; i <= t; i++) {
if (!p[i]) mu[i] = -1, p[++tot] = i;
for (int j = 1; j <= tot && i * p[j] <= t; j++) {
p[i * p[j]] = 1;
if (i % p[j] == 0) {
mu[i * p[j]] = 0; break;
}
mu[i * p[j]] = -mu[i];
}
}
}
bool check(int x) {
int t = sqrt(x), res = x;
for (int i = 2; i <= t; i++) {
res += x / (i * i) * mu[i];
}
return res < n;
}
int main() {
scanf("%d", &T), sieve();
while (T--) {
scanf("%d", &n);
ll l = n, r = n << 1, mid, res;
while (l <= r) {
check(mid = (l + r) >> 1) ? l = mid + 1 : r = (res = mid) - 1;
}
printf("%d\n", (int)res);
}
return 0;
}