【整体二分+莫比乌斯函数+容斥原理】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 }

 

posted @ 2016-07-01 14:21  iiyiyi  阅读(227)  评论(0编辑  收藏  举报