首先对 x,y 进行分类讨论(二进制形式)
1) y 1??????
x 0??????
------------------------------
y xor x 1???????
y mod x 0??????
不符合条件,对各种条件分类得知 只有以下情况符合题意
y 1??????
x 1??????
则此时 x<=y<2x
所以 推得
……………… (1)式
下面证明结论: y ^ x = y+x - 2 * (y & x)
考虑 y,x的每一位的值,共有四种情况
分类易知,(1,1)时的进位恰好被 2*(y&x) 减去
将该结论代入 (1)式,得到 y-x = y+x- 2*(y&x)
即 x = x & y
所以问题转化为:求 L<=x<=y<=R 中 有多少对 (x,y)满足 x = x&y
利用dp解决 (虽然我觉得我状态设计太多)
代码如下,注释在程序中:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll L,R;
ll f[64][2][2][2][2];
int l[100],r[100];
ll dfs(int x,int fl,int fr,int s,int ht)
{
if(x<0)return 1;
// x:第x位 (二进制转十进制下权值是1的为第0位)
// fl: y之前是否有填过小于 R的某一位的数字 例如:R:11000 y:10??? fl即为1 表示后面数字可以往大了填
// fr: x之前是否有填过大于 L的某一位的数字 类似fl
// s: 之前x是否有某一位 < y的某一位 如果有,后面的位数就没有相对大小限制了 (确保 x<=y)
//ht:确保 x,y 最高位一样都为1 (满足推导的要求)
ll &ans=f[x][fl][fr][s][ht];
if(ans)return ans;
for(int i=0;i<2;i++)//y
{
for(int j=0;j<2;j++)//x
{
int tl=fl,tr=fr,ts=s,tt=ht;
if(!tt&&i)if(i!=j)continue;
if((j&i)!=j)continue;
if(!tl&&j<l[x])continue;
if(!tr&&i>r[x])continue;
if(!ts&&j>i)continue;
if(j>l[x])tl=1;if(i<r[x])tr=1;if(j<i)ts=1;if(j)tt=1;
ans+=dfs(x-1,tl,tr,ts,tt);
}
}
ans%=mod;
return ans;
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>L>>R;
for(int i=63;i>=0;i--)
{
l[i]=(bool)((1ll<<i)&L);r[i]=(bool((1ll<<i)&R));
}
cout<<dfs(63,0,0,0,0);
return 0;
}