poj3252 Round Numbers
Round Numbers
题目大意:
输入两个十进制正整数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)); }