定义Round Number为二进制表示下0不少于1的数字。问区间[l,r]内有多少个Round Number。
仍然是考虑用[1,r]的答案减去[1,l-1]的答案。对于一个二进制长度为n的数x,显然长度为1~n-1的数必然是合法的。
首先看长度为n且小于x的数中有多少个合法答案。方法是从第二位开始,如果碰见1,就考虑如果它为0,可能产生多少种合法答案。以26=(11010)b为例,第二位是1,考如果它为0,此时有1个1和1个0,后面的3位里应有2个或3个0,则方案数C(3,2)+C(3,3)。然后到了第4位,如果它为0,此时已有2个1和2个0,最后一位要有1个0,方案数C(1,1)。依此类推。
然后计算二进制长度为x的数中有多少个是合法答案。首先第1位必然为1,则后面可能有1,2……(x-1)/2个1,即答案为C(x-1,1)+C(x-1,2)+……+C(x-1,(x-1)/2)。当x-1为奇数的时候答案为2^(x-2),x-1为偶数的时候答案为(2^(x-1)-C(x-1,(x-1)/2))/2。
/*嘤嘤嘤*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1050;
const ll INF = (1LL << 62) - 1;
const ll mod = 998244353;
int a, b;
ll C[35][35];
int num[35];
void init()
{
C[0][0] = C[1][0] = C[1][1] = 1;
for(int i = 2;i < 35;i++)
{
C[i][0] = 1;
for(int j = 1;j < i;j++)
C[i][j] = C[i-1][j-1] + C[i-1][j];
C[i][i] = 1;
}
}
ll getnum(int x)
{
x--;
if(x % 2 == 0) return ((1LL << x) - C[x][x/2])/2;
else return (1LL << x)/2;
}
ll cal(int n)
{
if(n <= 1) return 0;
int no = 0, na = 0, nb = 0;
while(n)
{
num[no++] = n % 2;
if(n % 2) nb++;
else na++;
n >>= 1;
}
ll ans = 0;
for(int i = 1;i <= no - 1;i++)
ans += getnum(i);
if(na >= nb) ans++;
na = 0, nb = 1;
for(int i = no - 2;i >= 0;i--)
{
if(num[i] == 1)
{
for(int j = i;j >= 0 && na + 1 + j >= nb + i - j;j--)
ans += C[i][j];
nb++;
}
else na++;
}
return ans;
}
int main()
{
init();
scanf("%d%d", &a, &b);
//cout<<cal(b) <<" "<<cal(a-1)<<endl;
printf("%lld\n", cal(b) - cal(a-1));
return 0;
}