poj3252 Round Numbers

Round Numbers

 POJ - 3252 

 题目大意:

输入两个十进制正整数a和b,求闭区间[a,b]内有多少个Round Number?

所谓的Round Number就是一个把十进制数转换成一个无符号二进制数,若该二进制数中0的个数大于等于1的个数,则它就是一个Round Number。

注意 转换所得的二进制数,最高位必然是1,最高位前不允许有0

【问题分析】

用前缀和思想:求出[0,a]和[0,b+1]内的答案,然后[0,b+1]-[0,a]

所以问题转向如何求[0,k]内有多少个Round Number。

首先把k转化成二进制数,并记录长度len。

计算分两步,第一步求出二进制长度小于len的情况,这种情况下得到的数一定在要求的范围内,所以直接按round number的性质组合就行

第二步求出二进制长度等于len的情况,这种情况下要保证得到的数在要求范围内的话,就只能依次把每位上的1变成0来讨论round number了

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int c[33][33]={0};
int bin[35];
void play_table(){
    for(int i=0;i<=32;i++)
        for(int 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];
}
void Bin(int n){
    memset(bin,0,sizeof(bin));
    while(n){
        bin[++bin[0]]=n&1;
        n>>=1;
    }
}
int round(int n){
    int sum=0;
    Bin(n);
    //计算长度小于bin[0]的所有二进制数中RN的个数 
    for(int i=1;i<bin[0]-1;i++)
        for(int j=i/2+1;j<=i;j++)
            sum+=c[i][j];
    //计算长度等于bin[0]的所有二进制数中RN的个数 
    int zero=0;
    for(int i=bin[0]-1;i>=1;i--){
        if(bin[i])
            for(int j=(bin[0]+1)/2-(zero+1);j<=i-1;j++)
                sum+=c[i-1][j];
        else zero++;
    }
    return sum;
}
int main(){
    play_table();
    int a,b;
    while(scanf("%d%d",&a,&b)!=EOF)  
        printf("%d\n",round(b+1)-round(a));
}

 

posted @ 2017-06-25 08:09  Echo宝贝儿  阅读(121)  评论(0编辑  收藏  举报