一、题目
二、解法
考虑二分答案,问题在于求出 n n n以内的所有满足条件数的个数。
从容斥方面考虑,个数 = = = 0 0 0个质数乘积平方的倍数个数 − - − 1 1 1个质数乘积平方的倍数 + + + 2 2 2个质数成绩平方的倍数 − - − 3 3 3个质数乘积平方的倍数 . . . . . . ...... ......
可以用莫比乌斯函数优化这个过程,形式化地表达,个数为:
∑
i
=
1
i
≤
n
μ
(
i
)
n
i
2
\sum_{i=1}^{i\leq\sqrt n} \mu(i)\frac{n}{i^2}
i=1∑i≤nμ(i)i2n时间复杂度
O
(
log
n
n
)
O(\log n\sqrt n)
O(lognn),贴个代码
q
w
q
qwq
qwq
#include <cstdio>
#define int long long
const int M = 50005;
int read()
{
int x=0,flag=1;
char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int T,k,cnt,vis[M],p[M],mu[M];
void init(int n)
{
mu[1]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i])
{
mu[i]=-1;
p[++cnt]=i;
}
for(int j=1;j<=cnt && i*p[j]<=n;j++)
{
vis[i*p[j]]=1;
if(i%p[j]==0) break;
mu[i*p[j]]=-mu[i];
}
}
}
int check(int x)
{
int res=0;
for(int i=1;i*i<=x;i++)
res+=mu[i]*(x/(i*i));
return res;
}
signed main()
{
T=read();
init(5e4);
while(T--)
{
k=read();
int l=1,r=k<<1,ans=1;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid)>=k) ans=mid,r=mid-1;
else l=mid+1;
}
printf("%lld\n",ans);
}
}