解题思路
动态规划,刚开始想的是dp[i][j][k]表示考虑了前i个数,A集合异或和为j,B集合异或和为k,时间复杂度O(n^3) ,得了50分。。正解应该是dp[i][j][k]表示前i个数,A^B=j,A与B第一位不同的数,B的这一位为k的方案数,因为要保证A < B,那么一定是A与B第x位之前的数相等,第x位B=1,A=0,首先枚举这一位数,然后用跑异或背包,因为前x位已经相等,所以答案应该在dp[n][2^i~2^(i+1)-1][1]中取。时间复杂度O(n^2logn)
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
using namespace std;
const int MAXN=4098;
const int mod=1e9+7;
int n,m,logg;
long long ans,dp[2][MAXN][2];
int main(){
scanf("%d%d",&n,&m);int mx=max(n,m);
logg=(int)log2(mx)+1;
for(register int i=0;i<=logg;i++){
memset(dp,0,sizeof(dp));dp[0][0][0]=1;
for(register int k=1;k<=mx;k++){
int now=(k>>i)&1;
for(register int j=0;j<(1<<logg);j++)
for(register int l=0;l<=1;l++){
dp[k&1][j][l]=dp[(k-1)&1][j][l];
if(k<=n) dp[k&1][j][l]+=dp[(k-1)&1][j^k][l];
if(k<=m) dp[k&1][j][l]+=dp[(k-1)&1][j^k][l^now];
dp[k&1][j][l]%=mod;
}
}
for(register int j=(1<<i);j<(1<<i+1);j++) ans+=dp[mx&1][j][1],ans%=mod;
}
cout<<ans<<endl;
return 0;
}