BZOJ2440 中山市选2011完全平方数(容斥原理+莫比乌斯函数)

  如果能够知道不大于n的合法数有多少个,显然就可以二分答案了。

  考虑怎么求这个。容易想到容斥,即枚举完全平方数。我们知道莫比乌斯函数就是此种容斥系数。筛出来就可以了。

  注意二分时会爆int。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define N 100010
#define inf 2000000000
int T,n,prime[N],mobius[N],cnt=0;
bool flag[N];
int calc(int n)
{
    int s=n;
    for (int i=2;i*i<=n;i++)
    s+=mobius[i]*(n/(i*i));
    return s;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("bzoj2440.in","r",stdin);
    freopen("bzoj2440.out","w",stdout);
    const char LL[]="%I64d\n";
#else
    const char LL[]="%lld\n";
#endif
    flag[1]=1;mobius[1]=1;
    for (int i=2;i<=N-10;i++)
    {
        if (!flag[i]) prime[++cnt]=i,mobius[i]=-1;
        for (int j=1;j<=cnt&&prime[j]*i<=N-10;j++)
        {
            flag[prime[j]*i]=1;
            if (i%prime[j]==0) break;
            mobius[prime[j]*i]=-mobius[i];
        }
    }
    T=read();
    while (T--)
    {
        n=read();
        unsigned int l=1,r=inf;int ans;
        while (l<=r)
        {
            int mid=l+r>>1;
            if (calc(mid)>=n) ans=mid,r=mid-1;
            else l=mid+1;
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

posted @ 2018-09-02 01:29  Gloid  阅读(185)  评论(0编辑  收藏  举报