题目大意: 找到第k个无平方因子数.
看到数据范围很大, 我们要采用比(O(n))还要小的做法.
考虑如果前(x)个数中有(k-1)个无平方因子数, 而前(x+1)个数中有(k)个无平方因子数, 那么(x)即为所求.
而由某种我不会的方式可以证明出答案是不会超过(2n)的, 所以我们可以二分答案.
问题就转化成了求前(x)个数中有多少个无平方因子数.
我们要求无平方因子数就要把所有的有平方因字数筛掉, 为了保证不重不漏, 我们考虑容斥.
我们枚举(1sim sqrt n)中的所有无平方因子数, 将其平方及其平方的倍数删掉.
这样的话有偶数个质因子的数就被多删了一遍, 我们再将他们加回来.
我们设容斥系数是(k(i)), 那么
[ans=sum_{i=1}^{left lfloor sqrt n
ight
floor}k(i){left lfloor frac n{i^2}
ight
floor}
]
而根据上面的分析, 容斥系数(k(i))满足:
[k(i)=left{egin{matrix}
0, 有平方因子\
1, 无平方因子, pi(i)是偶数\
-1, 无平方因子, pi(i)是奇数
end{matrix}
ight.
]
非常巧合的是, 这个容斥系数跟(mu)好像是一样的啊...
所以我们就可以得出
[ans=sum_{i=1}^{left lfloor sqrt n
ight
floor}mu(i){left lfloor frac n{i^2}
ight
floor}
]
这样预处理一波(mu), 然后每次(O(sqrt n))统计答案即可.
时间复杂度(O(T*log_2n*sqrt n))
代码:
#include <cstdio>
const int N=45005;
int pr[N],mu[N],tot,n;
bool np[N];
void shai(){
mu[1]=np[1]=1;
for(int i=2,k;i<=45000;++i){
if(!np[i]) pr[++tot]=i,mu[i]=-1;
for(int j=1;j<=tot&&(k=i*pr[j])<=45000;++j){
np[k]=1;
if(i%pr[j]==0){mu[k]=0; break;}
mu[k]=-mu[i];
}
}
}
inline bool check(int x,int s=0){
for(int i=1;i*i<=x;++i)
s+=x/(i*i)*mu[i];
return s>=n;
}
int main(){ shai();
int T; scanf("%d",&T);
while(T--){
scanf("%d",&n);
int l=1,r=n<<1;
while(l<r){
int mid=(1LL*l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
printf("%d
",r);
}
}
这个题并和莫比乌斯反演没什么关系, 算是莫比乌斯函数的一个小应用吧...