BZOJ:2440: [中山市选2011]完全平方数(容斥原理)

来源:互联网 发布:西储大学轴承数据 编辑:程序博客网 时间:2024/05/02 12:32

传送门

题意:

给你一个数k,求从1开始第k个非完全平方数。

定义一个数为完全平方数当且仅当这个数质因数分解后存在二次项。
如: 4=22为完全平方数,30=235为非完全平方数。

题解:
1.从1开始第k个非完全平方数min(n),比n小的非完全平方数有k个。有了这个性质,可以二分。
2.n小的非完全平方数个数=

i=1nμ(i)ni2

上面这个公式的本质是容斥。
即先减去质因数包含22,32,42,52...的个数,再加上包含2232等的个数,以此类推。
对于μ(d)可在线性时间类筛出。

不难发现时间复杂度为O(Tnlogn+n)

写代码是石乐志了。。还把前缀和算了。其实对于ni2相同的段很少很少,还是n级别的,不如直接枚举简便。

  • Code
#include<bits/stdc++.h>using namespace std;typedef long long ll;const int Maxn=5e4;inline int read(){    char ch=getchar();int i=0,f=1;    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}    while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}    return i*f;}int Prime[Maxn+50],pr[Maxn+50],tot,mu[Maxn+50];inline void sieve(){    mu[1]=1;    for(int i=2;i<=Maxn;i++)    {        if(!pr[i]){Prime[++tot]=i;pr[i]=i;mu[i]=-1;}        for(int j=1;j<=tot;j++)        {            int k=i*Prime[j];            if(k>Maxn)break;            pr[k]=Prime[j];            if(i%Prime[j]){mu[k]=-mu[i];}            else {mu[k]=0;break;}        }    }    for(int i=1;i<=Maxn;i++)mu[i]+=mu[i-1];}inline ll calc(int n){    int lim=sqrt(n);    int pos;    ll ans=0;    for(int bg=1;bg<=lim;bg=pos+1)    {        pos=min(lim,(int)sqrt(n/(n/bg/bg)));        ans+=1ll*(n/bg/bg)*(mu[pos]-mu[bg-1]);    }    return ans;}int main(){    sieve();    int T=read();    while(T--)    {        int k=read();        ll l=1,r=2e9,ans;        while(l<=r)        {            ll mid=(l+r)>>1;            if(calc(mid)>=k)ans=mid,r=mid-1;            else l=mid+1;        }        printf("%lld\n",ans);    }}
阅读全文
0 0
原创粉丝点击