题目大意:给两个数字a,b求出[a,b]中转化成二进制后0的个数大于等于1的个数的数
例如1100转化成10-11,100-111,1000-1011,1100。保证每个区段都有1打头,然后有一段数字任选用组合数求;
代码如下
#include<iostream> #include<string.h> #include<stdio.h> using namespace std; int a[40]; int c[50][50]; void table() { int i,j; for(i=0;i<=32;i++) { for(j=0;j<=i;j++) { if(!j||i==j) c[i][j]=1; else c[i][j]=c[i-1][j-1]+c[i-1][j]; } } return; } int sum(int n){ if(n == 0) return 0; int o = 0; //转化成二进制的位数 while(n){ a[o++] = n%2; n/=2; } int sum = 0; //ans int u = 0; //二进制前面1的个数-0的个数 for(int i = o-2; i >= 0; i--){ if(a[i] == 1){ if(i >= u){ for(int k = 0; k <= i; k++){ //1的个数 if(k + u <= i - k){//printf("%d %d %d ", i, k, c[i][k]); sum += c[i][k]; } } } u++; }else u--; } //printf("%d %d ", u, o); u++; if(u <= 0){ sum ++; } for(int i = 1; i < o-1; i++){ for(int k = 0; k <= i; k++){ if(1+k <= i-k){ sum += c[i][k]; } } } return sum; } int main(){ int a, b; table(); while(scanf("%d%d", &a, &b)!=EOF){ printf("%d ",sum(b) - sum(a-1)); } }