POJ-3252 Round Numbers 按位DP
前面用组合数学来写这题实在是被边界条件搞得头昏脑胀,这里就直接按位DP,每次dfs传递0和1的个数这两个参数下去即可。
代码如下:
#include <cstdlib> #include <cstdio> #include <cstring> using namespace std; int a, b, bit[35], dp[35][35][35]; int dfs(int pos, int zero, int one, int limit) { if (pos == -1) { return zero >= one; } if (!limit && dp[pos][zero][one] != -1) { return dp[pos][zero][one]; } int sum = 0, _o, _z, end = limit ? bit[pos] : 1; for (int i = 0; i <= end; ++i) { _o = one, _z = zero; if (i == 1) _o = one + 1; else if (i == 0 && one) _z = zero + 1; sum += dfs(pos-1, _z, _o, limit && i==end); } if (!limit) dp[pos][zero][one] = sum; return sum; } int Cal(int x) { int idx = -1; while (x) { bit[++idx] = x % 2; x /= 2; } return dfs(idx, 0, 0, 1); } int main() { memset(dp, 0xff, sizeof (dp)); while (scanf("%d %d", &a, &b) == 2) { a -= 1; printf("%d\n", Cal(b) - Cal(a)); } return 0; }