首页 > 代码库 > POJ 3252 Round Numbers 数位dp
POJ 3252 Round Numbers 数位dp
http://poj.org/problem?id=3252
题意:问从a到b有多少个round number。如果某数的二进制表示中0的个数不少于1的个数,那么它就是一个round number。
分析:数位dp。就我目前碰到的几道数位dp来说,其实所谓数位dp,就是和组合数有联系的递推罢了。还是转换为从0到a,我们先考虑二进制下长度小于a的数,即随便填0和1,那么就是用组合数算一下就可以了。然后考虑长度相等的,我们从高位往下走,已经枚举的就默认是a对应位的数。如果当前位是0,我们累计0的个数然后继续,如果是1,那么就可以变成0来考虑,之后的数又可以随便填,也是组合数算一下。这里会漏掉0和这个数本身,再单独算一下就行。
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 5 int a, b; 6 int c[40][40]; 7 int d[40]; 8 void init() 9 {10 for (int i = 0; i <= 32; i++){11 c[i][0] = 1;12 for (int j = 1; j <= i; j++)13 c[i][j] = c[i][j-1] * (i-j+1) / j;14 }15 }16 int cal(int x)17 {18 if (x == -1) return 0;19 int ret = 1, len = 0; //初始值为1,即0这个数20 while(x){21 d[len++] = x & 1;22 x >>= 1;23 }24 for (int i = 1; i < len; i++) //长度为i(小于x的长度)25 for (int j = 0; j+1 <= i/2; j++) //第一位为1,枚举之后有j个126 ret += c[i-1][j];27 int zero = 0, one = 1;28 for (int i = len-2; i >= 0; i--){29 if (d[i]){30 zero++;31 for (int j = 0; j <= i && j+one <= zero+(i-j); j++)32 ret += c[i][j];33 zero--;34 one++;35 }36 else zero ++;37 }38 if (zero >= one) ret++; //单独算x本身39 return ret;40 }41 int main()42 {43 init();44 while(scanf("%d %d", &a, &b) != EOF)45 {46 printf("%d\n", cal(b) - cal(a-1));47 }48 return 0;49 }
POJ 3252 Round Numbers 数位dp
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。