題目鏈接: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;
}