BZOJ 2440 完全平方数-莫比乌斯函数

题目描述

1.n的不大确定+f(n)([1,n]中不是平方数的倍数的数的个数)递增 -> 二分
2.容斥原理:f(x)=1的倍数-一个质数的倍数+2个质数乘积的倍数-… ;
f(x)=sigma(mu[i]*floor(x/(i*i))) ,1<=i<=floor(sqrt(x))

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAXN 500000
#define INF 2000000000
typedef long long LL;

LL mu[MAXN+10],prime[MAXN+10],cntpr,k;
bool isprime[MAXN+10];

void CalMobius(LL n)
{
    memset(mu,0,sizeof mu);
    memset(isprime,0,sizeof isprime);
    cntpr=0;
    mu[1]=1;
    for(LL i=2;i<=n;i++){
        if(!isprime[i]){
            prime[++cntpr]=i;
            mu[i]=-1;
        }
        for(LL j=1;prime[j]*i<=n&&j<=cntpr;j++){
            isprime[prime[j]*i]=true;
            if(i%prime[j]==0){
                mu[prime[j]*i]=0;
                break;
            }
            mu[prime[j]*i]=-mu[i];
        }
    }
}
LL Quary(LL x)
{
    LL side=sqrt(x+0.5),ret=0;
    for(LL i=1;i<=side;i++)
        ret+=mu[i]*(x/(i*i)); //也不要加floor装逼了,这个也会导致TLE
    return ret;
}
void partition()
{
    LL l=1,r=INF,mid,ans;
    while(l<r){
        mid=(l+r)/2;
        if(Quary(mid)>=k){
            r=mid;
            ans=mid;
        }
        else
            l=mid+1;
    }
    printf("%lld\n",ans);
}
int main()
{
    LL T;
    scanf("%lld",&T);
    CalMobius(MAXN); //注意MAXN不要开大了,虽然是线性筛,但就是这个害得我TLE
    while(T--){
        scanf("%lld",&k);
        partition();
    }
}
posted @ 2016-01-26 19:56  KatarinaYuan  阅读(145)  评论(0编辑  收藏  举报