2010-06-11 00:40 spoj1182 ,dp, number theory, binary search 数位类统计问题

2010-06-11 00:40 spoj1182 ,dp, number theory, binary search 数位类统计问题

详见国家集训队2009论文集 14.刘聪 <<浅谈数位类统计问题>>
这到题需要非常注意复数的操作,其实完全可以讲负数转化为整数操作
也就是int转换成unsigned int
还有就是要注意,int型正数,右移补0,负数右移是补1的,
  1 
  2  /*
  3   * SOUR:spoj1182
  4   * ALGO:dp, number theory, binary search
  5   * DATE: 2010年 06月 08日 星期二 19:47:51 CST
  6   * COMM:5
  7   *  */
  8  #include < iostream >
  9  #include < cstdio >
 10  #include < cstdlib >
 11  #include < cstring >
 12  #include < algorithm >
 13  #include < queue >
 14  #include < vector >
 15  #include < map >
 16  using   namespace  std;
 17  #define  pb(x) push_back(x)
 18  // #define X first
 19  // #define Y second
 20  typedef vector  <   int   > vi;
 21  typedef pair  <   int int   > pii;
 22  typedef  long   long  LL;
 23  typedef unsigned  long   long  ULL;
 24  typedef unsigned  int   uint ;
 25 
 26  template  < class  T >   void  ckmin(T  & a,T b) {  if  (a  >  b) { a  =  b; } }
 27  template  < class  T >   void  ckmax(T  & a,T b) {  if  (a  <  b) { a  =  b; } }
 28  int  countbit( int  n) {  return  n  ==   0   ?   0  :  1   +  countbit(n  &  (n  -   1 )); }
 29 
 30  const   int  maxint  =   0x7fffffff ;
 31  const   long   long  max64  =  0x7fffffffffffffffll;
 32  int  cnt[ 40 ][ 40 ], sum[ 40 ];
 33  int  X, Y, K;
 34 
 35  void  pre()
 36        // 算出cnt[长度][含多少个1]的方案数
 37  {
 38     int  i,j;
 39    cnt[ 0 ][ 0 =   1 ;
 40     for  (i  =   1 ;i  <=   32 ;i ++ ) {
 41        cnt[i][ 0 =  cnt[i - 1 ][ 0 ];
 42         for  (j  =   1 ;j  <=   32 ;j ++ ) {
 43            cnt[i][j]  =  cnt[i - 1 ][j]  +  cnt[i - 1 ][j - 1 ];
 44        }
 45    }
 46  }
 47 
 48  int  num[ 40 ], top;
 49  int  summ( uint  X,  int  R,  bool  flag  =   false )
 50  {
 51    memset(num,  0 sizeof (num));
 52    top  =   1 ;
 53     while  (X) {
 54        num[top ++ =  X  &   1 ;
 55        X  >>=   1 ;
 56    }
 57     if  (flag) {
 58         for  ( int  i  =   1 ;i  <=  top;i ++ ) {
 59             if  (num[i]  ==   0 ) {
 60                num[i]  =   1 ;
 61                 for  ( int  j  =  i  -   1 ;j  >=   1 ;j -- ) {
 62                    num[j]  =   0 ;
 63                }
 64                 if  (i  ==  top) { top ++ ; }
 65                 break ;
 66            }
 67        }
 68    }
 69     int  ans  =   0 , one  =   0 , i;
 70     for  (i  =  top  -   1 ;i  >=   1 ;i -- ) {
 71         if  (R  >=  one  &&  num[i]  ==   1 ) {
 72            ans  +=  cnt[i  -   1 ][R  -  one];
 73            one ++ ;
 74        }
 75    }
 76     return  ans;
 77  }
 78 
 79  int  summarize( uint  X,  uint  Y,  int  digit)
 80        // [X, Y] 中1的个数为digit的 数字个数
 81  return  summ(Y, digit,  1 -  summ(X, digit,  0 ); }
 82 
 83  void  proc()
 84  {
 85     int  i, j, one  =   - 1 ;
 86    memset(sum,  0 sizeof (sum));
 87     for  (i  =   0 ;i  <   32 ;i ++ ) {
 88        sum[i]  =  summarize(X, Y, i) ;
 89         if  (K   >  sum[i]) {
 90            K  -=  sum[i];
 91        } else  {
 92            one  =  i;
 93             break ;
 94        }
 95    }
 96     if  (Y  <  X) { swap(X, Y); }
 97     int  left  =  X, right  =  Y;
 98     while  (left  <  right) {  // binary search the value expected
 99         int  mid  =  (left  +  right  +   1 /   2 ;
100         if  (summarize(X, mid, one)  <=  K) {
101            left  =  mid;
102        } else  {
103            right  =  mid  -   1 ;
104        }
105    }
106     while  (countbit(left)  !=  one) { left  -- ; }  //  attention
107 
108     int  ans  =   0 ;
109     for  (i  =   0 ;i  <   32 ;i ++ ) {
110         if  (left  &  ( 1   <<  i)) {
111            ans  |=   1   <<  i;
112        }
113    }
114    printf( " %d\n " , ans);
115  }
116 
117  int  main()
118  {
119     int  i, j, testcase;
120    pre();
121    scanf( " %d " & testcase);
122     while  (testcase --  ) {
123        scanf( " %d %d %d " & X,  & Y,  & K);
124        proc();
125    }
126     return   0 ;
127  }
128 

你可能感兴趣的:(2010-06-11 00:40 spoj1182 ,dp, number theory, binary search 数位类统计问题)