Problem Description
小 X 自幼就很喜欢数。但奇怪的是,他十分讨厌完全平方数。他觉得这些数看起来很令人难受。由此,他也讨厌所有是完全平方数的正整数倍的数。然而这丝毫不影响他对其他数的热爱。
这天是小X的生日,小 W 想送一个数给他作为生日礼物。当然他不能送一个小X讨厌的数。他列出了所有小X不讨厌的数,然后选取了第 K个数送给了小X。小X很开心地收下了。
然而现在小 W 却记不起送给小X的是哪个数了。你能帮他一下吗?
Input
包含多组测试数据。文件第一行有一个整数 T,表示测试数据的组数。
第2 至第T+1 行每行有一个整数Ki,描述一组数据,含义如题目中所描述。
对于 100%的数据有 1 ≤ Ki ≤ 10^9, T ≤ 50
Output
含T 行,分别对每组数据作出回答。第 i 行输出相应的第Ki 个不是完全平方数的正整数倍的数。
Examples
Input
4
1
13
100
1234567Output
1
19
163
2030745
思路:
简单来说,题目是给出 t 组查询,每组给出一个 k,查找第 k 个不含完全平方因子的数
因此,直接考虑二分答案,计算第 k 个不含完全平方因子的数
对于区间 [1,n] 上的无完全平方因子数的个数,考虑 sqrt(n) 内的整数 a,由于含有平方因子的数需要排除,因此需要减去每个质数的平方的倍数的个数,但这样会使得减去的个数过多,例如 36 既被 4 减又被 9 减,因此需要再加上由质数乘积的平方的数的数,可以发现,这个过程是一个容斥的过程
然而问题在于,无法确定一个乘积平方的数是加还是减,但观察式子可以发现,一个数的乘积 x 的前面的系数就是 u(x)
那么,对于 n,n 以内的 a 的平方数的倍数有 n/(a^2) 个,因此,对于从 1 到 sqrt(n) 的所有整数 i,最终的结果就是 n/(i^2)*mu[i]
Source Program
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
#define Pair pair<int,int>
LL quickPow(LL a,LL b){ LL res=1; while(b){if(b&1)res*=a; a*=a; b>>=1;} return res; }
LL quickModPow(LL a,LL b,LL mod){ LL res=1; a=a%mod; while(b){if(b&1)res=(a*res)%mod; a=(a*a)%mod; b>>=1;} return res; }
LL getInv(LL a,LL mod){ return quickModPow(a,mod-2,mod); }
const double EPS = 1E-10;
const int MOD = 1E9+7;
const int N = 100000+5;
const int dx[] = {-1,1,0,0,-1,-1,1,1};
const int dy[] = {0,0,-1,1,-1,1,-1,1};
using namespace std;
int mu[N];
int prime[N];
bool bprime[N];
int cnt;
void getMu(int n){//线性筛求莫比乌斯函数
cnt=0;
mu[1]=1;//根据定义,μ(1)=1
memset(bprime,false,sizeof(bprime));
for(int i=2;i<=n;i++){//求2~n的莫比乌斯函数
if(!bprime[i]){
prime[++cnt]=i;//存储质数
mu[i]=-1;//i为质数时,μ(1)=-1
}
for(int j=1;j<=cnt&&i*prime[j]<=n;j++){//枚举i之前的素数个数
bprime[i*prime[j]]=true;//不是质数
if(i%prime[j])//i不是prime[j]的整数倍时,i*prime[j]就不会包含相同质因子
mu[i*prime[j]]=-mu[i];//mu[k]=mu[i]*mu[prime[j]],因为prime[j]是质数,mu值为-1
else{
mu[i*prime[j]]=0;
break;//留到后面再筛
}
}
}
}
LL cal(LL n){
LL res=0;
for(LL i=1;i*i<=n;i++)
res+=(n/(i*i)*mu[i]);
return res;
}
int main(){
getMu(100000);
int t;
scanf("%d",&t);
while(t--){
LL k;
scanf("%lld",&k);
LL res=0;
LL left=k,right=1E10;
while(left<=right){
LL mid=(left+right)/2;
if(cal(mid)<k)
left=mid+1;
else {
res=mid;
right=mid-1;
}
}
printf("%lld\n",res);
}
return 0;
}