这个题就是要你找在区间[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了;


#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; }