版权声明:作为一个蒟蒻,转载时请通知我这个蒟蒻 https://blog.csdn.net/zyszlb2003/article/details/89707205
题面描述
思路
很明显地,一个数不属于完全平方数或完全平方数的倍数,它的 一定不等于0.
因此我们只要二分枚举 ,
计算 之中的非完全平方数
根据容斥原理: 以内非完全平凡数的个数为:
- 中一个质数( )的平方的倍数的数量+ 中两个质数之积( )的平方的倍数的数量-…
所以我们可以枚举 , 是否等于0,就说明它是否是一个完全平方数。若 ,则是。
恰好就是非完全平方数的个数。
二分判断即可。
AC code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#define ll long long
#define gc getchar()
using namespace std;
const int N=5e4+10;
const int M=3e4+10;
const int inf=5e4;
inline void qr(ll &x)
{
x=0;int f=1;char c=gc;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
while(c>='0'&&c<='9'){x=(x*10)+(c^48);c=gc;}
x*=f;
}
int prime[M],m,mu[N];bool v[N];
inline void g_p()
{
m=0;memset(v,false,sizeof(v));mu[1]=1;
for(int i=2;i<=inf;i++)
{
if(!v[i])prime[++m]=i,mu[i]=-1;
for(int j=1;j<=m&&i*prime[j]<=inf;j++)
{
v[i*prime[j]]=1;
if(i%prime[j]==0){mu[i*prime[j]]=0;break;}
mu[i*prime[j]]=-mu[i];
}
}
}
ll k;
ll calc(ll x)
{
int t=sqrt(x);ll ans=0;
for(ll i=1;i<=t;i++)
ans+=mu[i]*(x/(i*i));//容斥
return ans;
}
int main()
{
g_p();
ll t;qr(t);
while(t--)
{
qr(k);
ll l=0,r=1644934081;
while(l<r)
{
ll mid=(l+r)>>1;//配套
if(calc(mid)>=k)r=mid;
else l=mid+1;
}
printf("%lld\n",l);
}
return 0;
}