您的位置:首页 > 其它

[二分+容斥+莫比乌斯函数] BZOJ2440: [中山市选2011]完全平方数

2017-07-02 16:36 239 查看

题意

求从小到大第k个无平方因子数是多少。(原题面表述略有问题)

k<=1e+9

题解

这题与反演无关,就用到了莫比乌斯函数。

首先肯定二分答案然后验证,现在问题转化为了求[1,mid]中无平方因子数的个数。

怎么求呢?考虑容斥,(p是1~sqrt(m)内的质数集)

总个数=[(pi)2的倍数]−[(pi∗pj)2的倍数]+[(pi∗pj∗pk)2的倍数]−[(pi∗pj∗pk∗pt)2的倍数]......

怎么求和呢?通过观察我们发现,对于任意[x2的倍数]这一项的前面的系数正好是mu[x]啊。

然后就完美解决了,

ans1到m无平方因子数的个数=∑⌊m√⌋iμ(i)∗⌊m/i2⌋

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=100015, N=100000;
int _test,n,m,mu[maxn],p[maxn];
LL ans;
bool vis[maxn];
void get_mu(){
memset(vis,1,sizeof(vis));
mu[1]=1;
for(int i=2;i<=N;i++){
if(vis[i]) p[++p[0]]=i, mu[i]=-1;
for(int j=1;j<=p[0]&&i*p[j]<=N;j++){
vis[i*p[j]]=false;
if(i%p[j]==0){ mu[i*p[j]]=0; break; }
mu[i*p[j]]=-mu[i];
}
}
}
LL get(LL mid){
LL res=0;
int t=sqrt(mid);
for(LL i=1;i<=t;i++) res+=(mid/(i*i))*mu[i];
return res;
}
int main(){
freopen("bzoj2440.in","r",stdin);
freopen("bzoj2440.out","w",stdout);
get_mu();
scanf("%d",&_test);
while(_test--){
scanf("%d",&m);
LL L=m,R=1e+10; ans=1;
while(L<=R){
LL mid=(L+R)>>1;
if(get(mid)>=m) R=mid-1, ans=mid;
else L=mid+1;
}
printf("%lld\n",ans);
}
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐