题意:
一个数x是round number,要求x写成二进制形式的时候数位上0的个数要大于等于1的个数,题目要求求出给定范围内的round number个数。
思路:
既然求的是二进制,那么自然要用二进制的数位dp来判断,模式基本不变,另外保存两个变量one,zero分别表示搜索中1和0出现的个数,另外还有一个flag变量清除前导零的影响。
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
int a[100];
ll dp[70][70][70];
ll dfs(int pos, int one, int zero, bool flag, bool limit) {
if (pos == -1) {
if (one <= zero) return 1;
return 0;
}
if (!limit && flag && dp[pos][one][zero] != -1) return dp[pos][one][zero];
int up = limit ? a[pos] : 1;
ll res = 0;
for (int i = 0; i <= up; i++) {
if (i == 0) {
if (flag) res += dfs(pos - 1, one, zero + 1, flag, limit && a[pos] == i);
else res += dfs(pos - 1, one, zero, flag, limit && a[pos] == i);
}
else res += dfs(pos - 1, one + 1, zero, true, limit && a[pos] == i);
}
if (!limit && flag) dp[pos][one][zero] = res;
return res;
}
ll solve(ll x) {
int pos = 0;
while (x) {
a[pos++] = x % 2;
x /= 2;
}
return dfs(pos - 1, 0, 0, false, true);
}
int main() {
ll x, y;
memset(dp, -1, sizeof(dp));
scanf("%I64d%I64d", &x, &y);
printf("%I64d\n", solve(y) - solve(x - 1));
return 0;
}