Description
小 X 自幼就很喜欢数。但奇怪的是,他十分讨厌完全平方数。他觉得这些
数看起来很令人难受。由此,他也讨厌所有是完全平方数的正整数倍的数。然而
这丝毫不影响他对其他数的热爱。
这天是小X的生日,小 W 想送一个数给他作为生日礼物。当然他不能送一
个小X讨厌的数。他列出了所有小X不讨厌的数,然后选取了第 K个数送给了
小X。小X很开心地收下了。
然而现在小 W 却记不起送给小X的是哪个数了。你能帮他一下吗?
Input
包含多组测试数据。文件第一行有一个整数 T,表示测试
数据的组数。
第2 至第T+1 行每行有一个整数Ki,描述一组数据,含义如题目中所描述。
Output
含T 行,分别对每组数据作出回答。第 i 行输出相应的
第Ki 个不是完全平方数的正整数倍的数。
K <= 1e9
题解:首先二分,转换为计数问题。用莫比乌斯函数的特殊性质来容斥是很巧妙的套路!
而每个数都可以写成质数积,那么显然只要质数的平方的倍数就可以代替所有数的平方的倍数。
考虑质数个数,假设质数集PP,那么根据容斥原理,在[1,x][1,x]范围内的整数不能能分解的个数有:
其中AS=⌊xS⋅S⌋AS=⌊xS⋅S⌋,即[1,x][1,x]范围内S|TS|T的TT个数。
而我们考虑莫比乌斯函数的定义,发现当μ(x)=(−1)kμ(x)=(−1)k的定义恰好是指数均为1的定义!而符号又决定了容斥的符号!哈哈!
所以我们预处理mu后,因为根据每个数的最大平方因子为x−−√x,那么我们只要枚举x−−√x个数,然后用莫比乌斯来搞就行了!(from iwtwiioi)
然而为什么rank1速度是我的20倍
#include<bits/stdc++.h>
using namespace std;
#define maxn 100020
typedef long long ll;
int prime[maxn],tag[maxn],cnt,mu[maxn],tot,a[maxn];
int T,k;
void init(){
mu[1] = 1;
for (int i = 2 ; i <= 100000 ; i++){
if ( !tag[i] ) prime[++cnt] = i , mu[i] = -1;
for (register int j = 1 ; j <= cnt && i * prime[j] <= 100000 ; j++){
tag[i * prime[j]] = 1;
if ( (i % prime[j]) == 0 ){ mu[i * prime[j]] = 0; break; }
mu[i * prime[j]] = -mu[i];
}
}
for (register int i = 1 ; i <= 100000 ; i++) if ( mu[i] ) a[++tot] = i;
}
int check(ll x){
ll cur = 0;
for (register int i = 1 ; (ll)a[i] * a[i] <= x ; i++){
cur += (x / a[i] / a[i]) * mu[a[i]];
}
return cur >= k;
}
int main(){
scanf("%d",&T);
init();
while ( T-- ){
scanf("%d",&k);
ll l = 1 , r = k * 2ll,ans;
while ( l <= r ){
ll mid = (l + r) >> 1;
if ( check(mid) ) ans = mid , r = mid - 1;
else l = mid + 1;
}
cout<<ans<<endl;
}
return 0;
}