题目链接:http://poj.org/problem?id=3252
题意:给出区间[L,R], 统计区间[L,R]有多少个数的2进制0的个数不小于1的个数。
题解:dp[pos][start][det], 表示从start位开始,剩余pos位要处理,当前state(二进制0的个数-1的个数)的方案数。
为了防止det非负,同时加上35。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
const int maxn = 33;
int dp[maxn][maxn][70];
int dight[maxn];
int dfs(int pos, int start, int det, bool limit)
{
if(!pos) return det >= 35;
int &A = dp[pos][start][det];
if(!limit && ~A) return A;
int res = 0;
int up = limit ? dight[pos] : 1;
for(int i = 0;i <= up;i ++) {
if(i == 0 && pos == start) {
res += dfs(pos-1, start-1, det, limit&&i==dight[pos]);
} else {
int fg;
if(i == 0) fg = 1;
else fg = -1;
res += dfs(pos-1, start, det + fg, limit&&i==dight[pos]);
}
}
if(!limit) A = res;
return res;
}
int solve(int n)
{
int cnt = 0;
while(n) {
dight[++cnt] = n & 1;
n >>= 1;
}
return dfs(cnt, cnt, 35, 1); //
}
int main()
{
memset(dp, -1, sizeof(dp));
int st, ed;
scanf("%d %d", &st, &ed);
printf("%d\n", solve(ed)-solve(st-1));
return 0;
}