因为当(A<B)时,会存在在二进制下的一位,满足这一位B的这一位是(1),(A)的这一位是(0).
我们枚举最大的这一位。设为(x)吧。
设计状态。(dp[i][j][1/0])代表考虑了前i个数,异或和为j的情况下(B)的第(x)位为(1)或(0)有多少种情况。
然后随便转移一下,再随便统计答案一下就好了。
如果不知道如何转移,就看代码吧。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int mod=1e9+7;
int n,m,mx,dp[2100][2100][2],ans;
int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return sum*f;
}
int main(){
n=read();m=read();
mx=max(n,m);
int now=0;
for(int i=1;i<=mx;i<<=1){
now++;
memset(dp,0,sizeof(dp));
dp[0][0][0]=1;
for(int j=1;j<=mx;j++){
for(int k=0;k<=2047;k++){
if(j<=m){
dp[j][k][0]=(dp[j][k][0]+dp[j-1][k^j][0^((j&i)>>(now-1))])%mod;
dp[j][k][1]=(dp[j][k][1]+dp[j-1][k^j][1^((j&i)>>(now-1))])%mod;
}
if(j<=n){
dp[j][k][0]=(dp[j][k][0]+dp[j-1][k^j][0])%mod;
dp[j][k][1]=(dp[j][k][1]+dp[j-1][k^j][1])%mod;
}
dp[j][k][0]=(dp[j][k][0]+dp[j-1][k][0])%mod;
dp[j][k][1]=(dp[j][k][1]+dp[j-1][k][1])%mod;
}
}
for(int j=i;j<=min(i*2-1,2047);j++)ans=(ans+dp[mx][j][1])%mod;
}
printf("%d",ans);
return 0;
}