题意:求范围内每个二进制数的1的个数和。
题解:数位dp
d
p
[
i
]
dp[i]
dp[i]:小于 只有第
i
+
i+
i+1位为1的二进制数 的所有数1的和。
c
[
i
]
c[i]
c[i]:第
i
i
i位为1的数量。
对于1000,答案就是dp[3] = 2 * dp[2]+ c[2],即第
i
i
i位是否为1两种情况加上第
i
i
i位为1的数量。
考虑普遍情况,对于每一位上的1,还要考虑之前的1是否存在。
如100 100 100,对于第3个1,还要考虑100 000 100 和 100 100 100 两种情况。
看代码就明白了。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#include<sstream>
#include<iomanip>
#define ll long long
using namespace std;
ll a, b, dp[66], c[66], n[66];
ll solve(ll x) {
int cnt = 0;
while (x) {
n[++cnt] = x % 2;
x >>= 1;
}
ll ans = 0;
int tot = 0;
for (int i = cnt; i >= 1; i--) {
if (n[i]) {
ans += dp[i - 1] + tot * c[i - 1];
tot++;
}
}
ans += tot;
return ans;
}
void init() {
dp[0] = 0;
c[0] = 1;
for (int i = 1; i <= 60; i++) {
dp[i] = 2 * dp[i - 1] + c[i - 1];
c[i] = c[i - 1] * 2;
}
}
int main() {
init();
while (~scanf("%lld%lld", &a, &b)) {
printf("%lld\n", solve(b) - solve(a - 1));
}
return 0;
}