BZOJ 2440: [中山市选2011]完全平方数

想不到要用二分 QAQ 好蠢啊。。。

想想容斥,就是ans=n-n/(2*2)-n/(3*3)-…+n/(6*6)+…-…+…
6因为是2和3的倍数,分解质因数之后有两个质因数,所以在容斥里面是加。
那么每个数乘的系数其实就是莫比乌斯函数。。。

那筛一下莫比乌斯函数就好了。。然后二分一下就好了。。

#include<bits/stdc++.h>
#define me(a,x) memset(a,x,sizeof a)
using namespace std;
typedef long long LL;
const int N=50000;
inline int read(){
    char ch=getchar(); int x=0,f=1;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0'; ch=getchar();}
    return x*f;
}
int p[N/8],pl,m[N+2];
bool v[N+2];
void pre(){
    pl=0,m[1]=1;
    for(int i=2;i<=N;++i){
        if(!v[i]) p[++pl]=i,m[i]=-1;
        for(int j=1;j<=pl && p[j]*i<=N;++j){
            int k=p[j]*i; v[k]=1;
            if(i%p[j]==0){
                m[k]=0;
                break;
            }
            m[k]=-m[i];
        }
    }
}
int get(int x){
    int ret=0;
    for(int i=1;i*i<=x;++i)
        ret+=m[i]*x/(i*i);
    return ret;
}
int main()
{
    pre(); int T=read();
    while(T--){
        int n=read(),l=1,r=n<<1,ans;
        while(l<=r){
            int mid=((LL)l+r)>>1;
            if(get(mid)>=n)ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(BZOJ 2440: [中山市选2011]完全平方数)