欢迎大家访问我的老师的OJ———caioj.cn
题面描述
思路
很明显地,一个数不属于完全平方数或完全平方数的倍数,它的 μ \mu μ一定不等于0.
因此我们只要二分枚举 x x x,
计算 [ 1 , x ] [1,x] [1,x]之中的非完全平方数
根据容斥原理: x x x以内非完全平凡数的个数为:
x x x- [ 1 , x ] [1,x] [1,x]中一个质数( 2 , 3 , 5 , . . . 2,3,5,... 2,3,5,...)的平方的倍数的数量+ [ 1 , x ] [1,x] [1,x]中两个质数之积( 6 , 10 , 14 , . . . 6,10,14,... 6,10,14,...)的平方的倍数的数量-…
所以我们可以枚举 ∀ i ∈ [ 1 , ⌊ x ⌋ \forall i\in[1,\left\lfloor\\ \sqrt{x}\right\rfloor ∀i∈[1,⌊x⌋, μ ( i ) \mu(i) μ(i)是否等于0,就说明它是否是一个完全平方数。若 = 0 =0 =0,则是。
a n s = ∑ i = 1 ⌊ x ⌋ μ ( i ) ∗ ⌊ x / ( i ∗ i ) ⌋ ans=\sum\limits_{i=1}^{\left\lfloor\\ \sqrt{x}\right\rfloor}\mu(i)*\left\lfloor\\ x/(i*i)\right\rfloor ans=i=1∑⌊x⌋μ(i)∗⌊x/(i∗i)⌋恰好就是非完全平方数的个数。
二分判断即可。
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;
}