题意
问你从(1,1)到(n,m)异或和为 k 的路径有多少条?只能向右和向下走。
思路
我们从(1,1)到(n,m)直接爆搜会超时,我们可以从前往后搜一半记录走到横坐标为x的点的时候路径有多少条,从后往前搜一半,终点a[x][y]会被两条路都统计进去,在^a[x][y]就好了,统计答案即可。
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 25;
const int dx[] = {1, 0, -1, 0};
const int dy[] = {0, 1, 0, -1};
typedef long long LL;
int n, m;
LL k, a[MAXN][MAXN], ans;
unordered_map<LL, LL> mp[MAXN];
void dfs_pre(int x, int y, LL sum)
{
if (x+y == (n+m-2)/2) { mp[x][sum]++; return ; }
for (int i = 0; i < 2; i++)
{
int X = x+dx[i], Y = y+dy[i];
if (X >= 0 && Y >= 0 && X < n && Y < m)
dfs_pre(X, Y, sum^a[X][Y]);
}
}
void dfs_suf(int x, int y, LL sum)
{
if (x+y == (n+m-2)/2) { ans += mp[x][sum^k^a[x][y]]; return ; }
for (int i = 2; i < 4; i++)
{
int X = x+dx[i], Y = y+dy[i];
if (X >= 0 && Y >= 0 && X < n && Y < m)
dfs_suf(X, Y, sum^a[X][Y]);
}
}
int main()
{
scanf("%d%d%lld", &n, &m, &k);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
scanf("%lld", &a[i][j]);
dfs_pre(0, 0, a[0][0]);
dfs_suf(n-1, m-1, a[n-1][m-1]);
printf("%lld", ans);
return 0;
}
/*
3 3 11
2 1 5
7 10 0
12 6 4
*/