【整体二分+莫比乌斯函数+容斥原理】BZOJ2440
【题目大意】
求第k个不是完全平方数或完全平方数整数倍的数。
【思路】
由于μ(i)*(n/i^2)=n,可以直接从1开始,得出非完全平方数/完全平方数倍数的数的个数
注意一下二分的写法,这里用的是我一直比较喜欢的一种二分写法:
int lb=下界-1,ub=上界
while (ub-lb>1)
{
int mid=(lb+ub)>>1;
if (a[mid]>=k) ub=mid; else lb=mid;
}
ans=ub;
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long ll; 7 const ll MAXN=50000+50; 8 const ll INF=0x7fffffff; 9 int T; 10 ll k; 11 int miu[MAXN]; 12 ll prime[MAXN]; 13 int pnum=0; 14 15 void get_miu() 16 { 17 for (int i=0;i<MAXN;i++) miu[i]=-INF; 18 miu[1]=1; 19 for (int i=2;i<MAXN;i++) 20 { 21 if (miu[i]==-INF) 22 { 23 miu[i]=-1; 24 prime[++pnum]=i; 25 } 26 for (int j=1;j<=pnum;j++) 27 { 28 if (i*prime[j]>=MAXN) break; 29 if (i%prime[j]==0) miu[i*prime[j]]=0; 30 else miu[i*prime[j]]=-miu[i]; 31 } 32 } 33 } 34 35 ll square(ll x) 36 { 37 ll res=0; 38 for (int i=1;i*i<=x;i++) res+=miu[i]*(x/(i*i)); 39 return res; 40 } 41 42 ll get_ans() 43 { 44 ll lb=-1,ub=MAXN*MAXN; 45 while (ub-lb>1) 46 { 47 ll mid=(lb+ub)>>1; 48 ll nowk=square(mid); 49 if (nowk>=k) ub=mid; 50 else lb=mid; 51 } 52 return ub; 53 } 54 55 int main() 56 { 57 get_miu(); 58 scanf("%d",&T); 59 for (int i=0;i<T;i++) 60 { 61 scanf("%lld",&k); 62 printf("%lld\n",get_ans()); 63 } 64 return 0; 65 }