poj 3252 Round Numbers

这个题就是要你找在区间[l,r]之中有多到少个二进制数0的个数大于等于1的个数(没有前导0)

我的解题思路是:

先求出这个数有多少位n;然后进行组合排序:

 

排序要分两种情况:

第一种:就是位数小于n,我们假设要对m个数进行0与1的组合排序,那么m+1位一定是1;那么我们就只要举例到1~n-2位。

第二种:就是n位,第一位我们不管一定为1,那么我们就列举后面出现1的情况,如果为1,那么我们就把该位设为0,假设该位为m,那么m前面已经有k个0,那么到m位就有k+1个0了;

View Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<cstring>
#include<vector>
#include<string>
#define LL long long
using namespace std;
int c[33][33];
void Get_c( )
{
    for( int i = 0 ; i < 33 ; i ++ ){
         for( int j = 0 ; j <= i ; j ++ ){
              if( j == 0 || j == i )
                  c[i][j] = 1;
              else c[i][j] = c[i-1][j] + c[i-1][j-1];
        }    
    }
}
LL Solve( int n ){
  LL sum = 0;
  int len = 0,N=n;
  while( N ){
           len ++;
           N >>=1;
        }
  for( int i = 1; i < len -1 ; i ++ ){
       for( int j =  (i>>1) +1 ; j <= i  ; j ++ ){           
            sum += c[i][j]; 
       }
  }  
  int zero = 0;
  for( int i = len - 2  ; i >= 0 ; i -- ){
       if( ( n >> i )&1 == 1 ){
               for( int j = (( len + 1 )>>1) - zero - 1; j <= i ; j ++ ){
                  sum += c[i][j];
            }
       }
       else zero++;
  }
  return sum;
}
int main(  ){
    int l,r;
    Get_c( );
    while( scanf( "%d %d",&l,&r )==2 ){
          printf( "%I64d\n",Solve( r + 1 ) - Solve( l  ) );    
    }
    //system( "pause" );
    return 0;
}
posted @ 2012-08-10 11:06  wutaoKeen  阅读(141)  评论(0)    收藏  举报