# SRM601

500pts:

$dp\left[i\right]\left[a\right]\left[b\right]$$dp[i][a][b]$表示到了第$i$$i$个数，两个集合异或和为$a$$a$，第一个集合不同位是$b$$b$

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 2065, P = 1e9 + 7;
int n, m, ans, p;
int dp[maxn][maxn][2];
int dfs(int N, int mask, int b) {
if(N == 0) {
return mask == 1 && !b;
}
}
int ret = 0;
if(N <= n) {
ret = (ret + dfs(N - 1, mask ^ (N >> p), b ^ (N >> p & 1))) % P;
}
if(N <= m) {
ret = (ret + dfs(N - 1, mask ^ (N >> p), b)) % P;
}
ret = (ret + (dfs(N - 1, mask, b))) % P;
}
class WinterAndSnowmen {
public:
int getNumber(int N, int M) {
n = N;
m = M;
for(p = 0; p < 11; ++p) {
memset(dp, -1, sizeof(dp));
ans = (ans + dfs(max(n, m), 0, 0)) % P;
}
return ans;
}
};

1000pts:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 105, P = 1e9 + 7;
struct node {
int f, r, g, b;
int end() {
return f + r + g + b;
}
};
int n;
vector<node> s[505];
int f[maxn], r[maxn], g[maxn], b[maxn];
ll dp[505][maxn][maxn], c[505][505];
ll C(int A, int B, int C) {
return c[A + B + C][A] * c[B + C][B] % P;
}
ll dfs(int i, int r, int g) {
if(i == 501) {
return !r && !g;
}
if(dp[i][r][g] != -1) {
return dp[i][r][g];
}
ll ret = 0;
if(s[i].size() == 0) {
ret = dfs(i + 1, 0, 0);
} else if(s[i].size() == 1) {
if(i + 1 == s[i][0].end()) {
ret = dfs(i + 1, 0, 0);
} else {
if(r + 1 <= s[i][0].r) {
ret += dfs(i + 1, r + 1, g);
}
if(g + 1 <= s[i][0].g) {
ret += dfs(i + 1, r, g + 1);
}
if(i - s[i][0].f - r - g + 1 <= s[i][0].b) {
ret += dfs(i + 1, r, g);
}
ret %= P;
}
} else {
node s0 = s[i][0], s1 = s[i][1];
int b = i - s0.f - r - g;
if(s0.end() == s1.end()) {
if(s0.r - s1.r == r && s0.g - s1.g == g && s0.b - s1.b == b) {
ret = C(s1.r, s1.g, s1.b) * dfs(s0.end(), 0, 0) % P;
}
} else if(s0.end() < s1.end()) {
if(s0.r - r <= s1.r && s0.g - g <= s1.g && s0.b - b <= s1.b) {
ret = C(s0.r - r, s0.g - g, s0.b - b) * dfs(s0.end(), s0.r - r, s0.g - g) % P;
}
} else {
if(s0.r - r - s1.r >= 0 && s0.g - g - s1.g >= 0 && s0.b - b - s1.b >= 0) {
ret = C(s1.r, s1.g, s1.b) * dfs(s1.end(), r + s1.r, g + s1.g) % P;
}
}
}
return dp[i][r][g] = ret;
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
scanf("%d", &f[i]);
}
for(int i = 1; i <= n; ++i) {
scanf("%d", &r[i]);
}
for(int i = 1; i <= n; ++i) {
scanf("%d", &g[i]);
}
for(int i = 1; i <= n; ++i) {
scanf("%d", &b[i]);
}
for(int i = 1; i <= n; ++i) {
for(int j = f[i]; j < f[i] + r[i] + g[i] + b[i]; ++j) {
s[j].push_back((node){f[i], r[i], g[i], b[i]});
}
}
c[0][0] = 1;
for(int i = 1; i <= 500; ++i) {
c[i][0] = 1;
for(int j = 1; j <= i; ++j) {
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % P;
}
}
for(int i = 0; i <= 500; ++i) {
if(s[i].size() == 2) {
if(s[i][0].f > s[i][1].f) {
swap(s[i][0], s[i][1]);
}
}
}
memset(dp, -1, sizeof(dp));
printf("%lld\n", dfs(0, 0, 0));
return 0;
}