题意
求自然数中,第\(k\)个不含平方因子的数
思路
这道题的做法还挺多的(打表,二分,反演...)
我用的做法是二分+容斥
显然答案满足二分性,假设当前检验的数为\(n\)
没有平方因子的数=所有数-一个质数平方的因子的倍数+两个质数乘积平方的倍数-三个的.......
对于一个数\(i^2\),可以发现\(\mu (i)\)就是\(i^2\)在上面那个式子中的系数,所以上式可以表示为\[ans=\sum_{i=1}^{i^2\leq n}{\mu (i)\times \frac{n}{i^2}}\]
一遍\(check\)是\(\sqrt {n}\),所以整个算法复杂度为\(O(logn\sqrt {n})\)
Code
#include<bits/stdc++.h>
#define N 50005
using namespace std;
typedef long long ll;
int T;
int p[N],mu[N],cnt;
ll k;
bool isnotp[N];
template <class T>
void read(T &x)
{
char c;int sign=1;
while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
}
void init(int maxn)
{
isnotp[1]=1;
mu[1]=1;
for(int i=2;i<=maxn;++i)
{
if(!isnotp[i]) p[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&(ll)p[j]*i<=maxn;++j)
{
isnotp[p[j]*i]=1;
if(i%p[j]==0)
{
mu[i*p[j]]=0;
break;
}
else mu[i*p[j]]=-mu[i];
}
}
}
bool check(ll x)//[1,x]>=k ?
{
ll ret=0;
for(ll i=1;i*i<=x;++i) ret+=mu[i]*(x/(i*i));
return ret>=k;
}
int main()
{
read(T);
init(N-5);
while(T--)
{
ll l=1,r=5000000000LL,ans=0;
read(k);
while(l<=r)
{
ll mid=(l+r)>>1;
if(check(mid)) r=mid-1,ans=mid;
else l=mid+1;
}
printf("%lld\n",ans);
}
return 0;
}