BZOJ 2440 完全平方数

来源:互联网 发布:数据存储计量单位 编辑:程序博客网 时间:2024/05/22 04:46

BZOJ 2440 完全平方数
参考PoPoQQQ神的ppt

首先二分答案 问题转化为求[1,x]之间有多少个无平方因子数
根据容斥原理可知 对于sqrt(x)以内所有的质数 有
x以内的无平方因子数
=0个质数乘积的平方的倍数的数的数量(1的倍数)
-每个质数的平方的倍数的数的数量(9的倍数,25的倍数,…)
+每2个质数乘积的平方的倍数的数的数量(36的倍数,100的倍数,…)-…

容易发现每个乘积a前面的符号恰好是 μ(a)(例如μ(3)=1,故9对答案的贡献为负;μ(6)=1,故36对答案的贡献为正)

x以内i2的倍数有xi2个 故有Q(x)=xi=1xi2

#include <bits/stdc++.h>using namespace std;typedef long long LL;const int N= 1e6+10;int prime[N],tot;int mu[N];void Mu(){    mu[1]=1;    for (int i=2;i<N;i++){        if (!prime[i]){            prime[++tot]=i;            mu[i]=-1;        }        for (int j=1;prime[j]*i<N;j++){            prime[prime[j]*i]=1;            if (i%prime[j]==0){                mu[i*prime[j]]=0;                break;            }            mu[i*prime[j]]=-mu[i];        }    }    //for (int i=1;i<=100;i++) printf("%d %d\n",i,mu[i]);}LL calc(LL mid){    LL ans=0;    for (LL i=1;i*i<=mid;i++){        ans+=mu[i]*(mid/(i*i));    }    return ans;}void work(){    int K ;    cin>>K;    LL L=1,R=1LL<<32,mid,ans=1;    while (L<=R){        LL mid=(L+R)>>1;        LL ret=calc(mid);        if (ret>=K)R=mid-1,ans=mid;        else       L=mid+1;    }    cout<<ans<<endl;}int main(){    Mu();    int Case;scanf("%d",&Case);    while (Case--){        work();    }    return 0;}
原创粉丝点击