bzoj2440 - 完全平方数(莫比乌斯函数,容斥原理)
题目
小 X 自幼就很喜欢数。但奇怪的是,他十分讨厌完全平方数。他觉得这些
数看起来很令人难受。由此,他也讨厌所有是完全平方数的正整数倍的数。然而
这丝毫不影响他对其他数的热爱。
这天是小X的生日,小 W 想送一个数给他作为生日礼物。当然他不能送一
个小X讨厌的数。他列出了所有小X不讨厌的数,然后选取了第 K个数送给了
小X。小X很开心地收下了。
然而现在小 W 却记不起送给小X的是哪个数了。你能帮他一下吗?
题解
容易想到二分答案,故关键在于求区间[1, n]中不含平方因子的数个数,设这个函数为\(f(n)\)。
假设[1, n]中含有质数\(p_1,p_2,...p_k\),由容斥原理可得
\[f(n)=n-(\lfloor\frac{n}{p_1^2}\rfloor+\lfloor\frac{n}{p_2^2}\rfloor+...+\lfloor\frac{n}{p_k^2}\rfloor)+(\lfloor\frac{n}{p_1^2p_2^2}\rfloor+\lfloor\frac{n}{p_1^2p_3^2}\rfloor+...+\lfloor\frac{n}{p_1^2p_k^2}\rfloor+...)-(...)+(...)-...
\]
因为分母是平方数,我们可以枚举分母的值,枚举复杂度为\(O(\sqrt{n})\)。那么前面系数怎么求?容易发现,这个系数就是莫比乌斯函数的值!质因数个数为奇数时减 和 质因数个数为偶数时加 真好对应莫比乌斯函数的\((-1)^k\)。根号下分母不存在含平方质因子的情况,正好对应莫比乌斯函数为零的情况。故有
\[f(n)=\sum\limits^{i^2\le n}_{i=1}{\mu(i)\lfloor\frac{n}{i^2}\rfloor}
\]
也可以写成
\[\sum\limits^{n}_{i=1}{\mu(i)^2}=\sum\limits^{i^2\le n}_{i=1}{\mu(i)\lfloor\frac{n}{i^2}\rfloor}
\]
#include <bits/stdc++.h>
#define endl '\n'
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define mp make_pair
#define seteps(N) fixed << setprecision(N)
typedef long long ll;
using namespace std;
/*-----------------------------------------------------------------*/
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
#define INF 0x3f3f3f3f
const int N = 1e5 + 10;
const double eps = 1e-5;
int mu[N];
int prime[N];
bool vis[N];
int cnt;
void init() {
mu[1] = 1;
for(int i = 2; i < N; i++) {
if(!vis[i]) {
prime[cnt++] = i;
mu[i] = -1;
}
for(int j = 0; j < cnt; j++) {
int p = prime[j];
if(i * p > N) break;
vis[i * p] = 1;
if(i % p == 0) {
mu[i * p] = 0;
break;
}
mu[i * p] = -mu[i];
}
}
}
ll get(ll n) {
ll res = 0;
for(int i = 1; 1ll * i * i <= n; i++) {
res += mu[i] * (n / (1ll * i * i));
}
return res;
}
int main() {
IOS;
init();
int t;
cin >> t;
while(t--) {
int k;
cin >> k;
ll l = 1, r = 1800000000;
while(l <= r) {
ll mid = (l + r) / 2;
if(get(mid) >= k) {
r = mid - 1;
} else {
l = mid + 1;
}
}
cout << l << endl;
}
}