1. 程式人生 > >BZOJ 2440 完全平方數-莫比烏斯函式

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(); } }