题目链接:https://vjudge.net/problem/POJ-3252
题意:l - r 二进制 0 数目大于等于 1的数目 的数量
题解:dp[ i][j ][k ] 表示还剩 i 位,前面 0 的数目+ 32 - 1的数目为j, k表示前面是否全为0
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
int dp[35][65][2];
int w[66], len;
int dfs(int pos, int limit, int pre, int lead) {
if(pos < 0) return pre >= 32;
if(!limit && dp[pos][pre][lead] != -1) return dp[pos][pre][lead];
int p = limit ? w[pos] : 1;
int res = 0;
for(int i = 0; i <= p; i++) {
if(lead && i == 0)
res += dfs(pos - 1, limit && i == p, pre, 1);
else
res += dfs(pos - 1, limit && i == p, pre + (i == 0 ? 1 : -1), 0);
}
if(!limit) dp[pos][pre][lead] = res;
return res;
}
int solve(int x) {
if(x == 0) return 1;
int len = 0;
while(x) {
w[len++] = x % 2;
x /= 2;
}
return dfs(len - 1, 1, 32, 1);
}
int main() {
int l, r;
memset(dp, -1, sizeof(dp));
while(~scanf("%d %d", &l, &r))
printf("%d\n", solve(r) - solve(l - 1));
return 0;
}