题意:
求出第 (ki) 个不是完全平方数的整数倍的数。((1) 是第一个)
数据范围:(1 ≤ Ki ≤ 10^9,T ≤ 50)
分析:
首先可以想到,用容斥定理来求。但实际上,完全平方数有很多,不可能一个一个地枚举出来,然后奇加偶减。
对于 (sqrt{n}) 以内的素数集合:(s),(n) 以内的不含完全平方数因子的数的个数:
(ans=frac{n}{1*1}-frac{n}{2*2}-frac{n}{3*3}-frac{n}{5*5}+frac{n}{6*6}...)
显然,偶数个质数平方对于答案的贡献就是正的,否则是负;如果不是若干个互异质数的乘积,那么对答案没有影响,因为它们已经被所含的质数处理过。
所以:
[ans=sum_{i=1}^{sqrt{n}}{mu[i]*frac{n}{i*i}}
]
结合二分即可找出符合条件的数。
注意:
1.二分时,是找到第一个满足条件的数,所以在改变区间时要注意写法;
2.二分时,(l+r) 会爆 (int) 。
代码:
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;
const int N=1e5+5;
int mu[N];
vector<int>prime;
bool vis[N];
void read(int &x)
{
x=0;
int f=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<3)+(x<<1)+ch-'0';
ch=getchar();
}
x*=f;
}
void init()
{
mu[1]=1;
memset(vis,0,sizeof(vis));
for(int i=2;i<=N-5;i++)
{
if(!vis[i])
{
prime.pb(i);
mu[i]=-1;
}
for(int j=0;j<prime.size()&&1LL*prime[j]*i<=N-5;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
else
mu[i*prime[j]]=-mu[i];
}
}
}
ll solve(int n)
{
ll ans=0;
for(int i=1;1LL*i*i<=n;i++)
ans+=(mu[i]*n/(i*i));
return ans;
}
int main()
{
int t,k;
init();
read(t);
while(t--)
{
read(k);
ll l=1,r=2*k+5;
while(l<=r)
{
ll mid=(l+r)>>1;
ll t=solve(mid);
if(t<k)
l=mid+1;
else
r=mid-1;
}
printf("%lld
",l);
}
return 0;
}