solution:
一道比较难想的dp吧,看了题解才知道题目的突破口就是这个性质:
A<B当且仅当A^B的最高位是1的那一位上B为1而A为0
有了这个性质就可以考虑异或dp
设f[i][j][0/1]表示当前处理到第i个数,A^B=j,B的第x位为0/1(x就是上面所说的最高位)的方案数
然后最外层枚举x,内层算出当前f数组,将j为2^x~2^(x+1)的f[max(n,m)][j][1]加到ans里
用滚动数组优化一下空间
具体细节看注释
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int mod=1e9+7;
int n,m,f[2][2048][2],ans,mx;
int main(){
scanf("%d%d",&n,&m); mx=max(m,n);
for(int i=0;(1<<i)<=mx;i++){//A^B的最高位为i
memset(f,0,sizeof f);
int now=1,pre=0;
f[pre][0][0]=1;
for(int j=1;j<=mx;j++,now^=1,pre^=1){//枚举处理到了第j个
memcpy(f[now],f[pre],sizeof f[now]);
int t=((j&(1<<i)))>0;//j这个数在i位上是不是1
for(int k=0;k<2048;k++){//枚举异或和
if(j<=n)//j这个数放到X中
(f[now][k][0]+=f[pre][k^j][0])%=mod,
(f[now][k][1]+=f[pre][k^j][1])%=mod;
if(j<=m)//j这个数放到Y中
(f[now][k][0]+=f[pre][k^j][t])%=mod,
(f[now][k][1]+=f[pre][k^j][t^1])%=mod;
}
}
for(int j=(1<<i);j<(1<<(i+1));j++) (ans+=f[pre][j][1])%=mod;
}
printf("%d\n",ans);
return 0;
}