poj3252 组合数学

题目大意:给两个数字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));
    }
}
View Code
原文地址:https://www.cnblogs.com/icodefive/p/4234608.html