考虑不限制xor{Y}>xor{X}
- 考虑n=m的情况,每个数i∈[1,n]可以被分配到X集合或Y集合,或不分配
- 设f[S]表示{X} xor {Y} == S的方案数
- 有f[S]+=2*f[S^i]
- 考虑n!=m,那就是多余的部分得强制分配,分开两个转移即可
考虑限制xor{Y}>xor{X}
- 对于数B>A,在二进制表示下,就是B和A的前面相等,直到某一位B为1,A为0,之后无所谓
- 枚举这一位k,限制B(xor{Y})第k位为1,且B xor A第k位为0(统计答案限制范围)
- 状态加一维f[S][0/1]表示A xor B==S且B的第k位是0/1
- 转移分开讨论两个情况
- 1.放进X集合,直接继承状态
- 2.放进Y集合,根据i第k位转移
#include<iostream> #include<cstring> #include<cstdio> using namespace std; inline int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } const int MOD = 1000000007; const int MAXN = 4096; int n,m; long long f[MAXN][2],g[MAXN][2]; long long ans; int main(){ n=rd();m=rd(); int mx=max(n,m),tmp=mx; int len=0; while(tmp){len++;tmp>>=1;} for(int k=1;k<=len;k++){ memset(f,0,sizeof(f)); f[0][0]=1; for(int i=1;i<=mx;i++){ memcpy(g,f,sizeof(f)); for(int s=mx<<1;s>=0;s--){ if(i<=n){ f[s][0]+=g[s^i][0]; f[s][1]+=g[s^i][1]; } if(i<=m){ f[s][0]+=g[s^i][(i>>(k-1))&1]; f[s][1]+=g[s^i][((i>>(k-1))+1)&1]; } f[s][0]%=MOD;f[s][1]%=MOD; } } for(int i=(1<<(k-1));i<(1<<k);i++){ ans+=f[i][1]; } ans%=MOD; } cout<<ans; return 0; }