# bzoj 2440

“满足某种限制的数的第k个”+二分答案="前n个数有多少个数满足限制“

|A1 U A2 U A3 ... | = |A1|+|A2|+|A3|-|A1 and A2|-|A1 and A3|-|A2 and A3|+|A1 and A2 and A3|

 1 /**************************************************************
2     Problem: 2440
3     User: idy002
4     Language: C++
5     Result: Accepted
6     Time:1232 ms
7     Memory:1232 kb
8 ****************************************************************/
9
10 #include <cstdio>
11 #include <cmath>
12
13 int prm[6000], isnot[50010], mu[50010], ptot;
14
15 void init() {
16     mu[1] = 1;
17     for( int i=2; i<=50000; i++ ) {
18         if( !isnot[i] ) {
19             prm[++ptot]=i;
20             mu[i] = -1;
21         }
22         for( int j=1; j<=ptot && prm[j]*i<=50000; j++ ) {
23             isnot[i*prm[j]]=true;
24             if( i%prm[j]==0 ) {
25                 mu[i*prm[j]]=0;
26                 break;
27             }
28             mu[i*prm[j]]=-mu[i];
29         }
30     }
31 }
32 int calc( int n ) {
33     int rt = 0;
34     int maxi = (int)ceil(sqrt(n));
35     for( int i=1; i<=maxi; i++ )
36         rt += mu[i]*(n/(i*i));
37     return rt;
38 }
39 int nth( int k ) {
40     int lf=1, rg=2000000000;
41     while( lf<rg ) {
42         int mid=lf+((rg-lf)>>1);
43         int cnt=calc(mid);
44         if( cnt<k ) lf=mid+1;
45         else rg=mid;
46     }
47     return lf;
48 }
49
50 int main() {
51     int T;
52     init();
53     scanf( "%d", &T );
54     while( T-- ) {
55         int k;
56         scanf( "%d", &k );
57         printf( "%d\n", nth(k) );
58     }
59 }
View Code

posted @ 2015-03-29 21:57  idy002  阅读(217)  评论(0编辑  收藏  举报