https://codeforces.com/problemset/problem/1006/F
F. Xor-Paths
time limit per test3 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
There is a rectangular grid of size n×m. Each cell has a number written on it; the number on the cell (i,j) is ai,j. Your task is to calculate the number of paths from the upper-left cell (1,1) to the bottom-right cell (n,m) meeting the following constraints:
You can move to the right or to the bottom only. Formally, from the cell (i,j) you may move to the cell (i,j+1) or to the cell (i+1,j). The target cell can’t be outside of the grid.
The xor of all the numbers on the path from the cell (1,1) to the cell (n,m) must be equal to k (xor operation is the bitwise exclusive OR, it is represented as ‘^’ in Java or C++ and “xor” in Pascal).
Find the number of such paths in the given grid.
Input
The first line of the input contains three integers n, m and k (1≤n,m≤20, 0≤k≤1018) — the height and the width of the grid, and the number k.
The next n lines contain m integers each, the j-th element in the i-th line is ai,j (0≤ai,j≤1018).
Output
Print one integer — the number of paths from (1,1) to (n,m) with xor sum equal to k.
Examples
inputCopy
3 3 11
2 1 5
7 10 0
12 6 4
outputCopy
3
inputCopy
3 4 2
1 3 3 3
0 3 3 2
3 0 1 1
outputCopy
5
inputCopy
3 4 1000000000000000000
1 3 3 3
0 3 3 2
3 0 1 1
outputCopy
0
Note
All the paths from the first example:
(1,1)→(2,1)→(3,1)→(3,2)→(3,3);
(1,1)→(2,1)→(2,2)→(2,3)→(3,3);
(1,1)→(1,2)→(2,2)→(3,2)→(3,3).
All the paths from the second example:
(1,1)→(2,1)→(3,1)→(3,2)→(3,3)→(3,4);
(1,1)→(2,1)→(2,2)→(3,2)→(3,3)→(3,4);
(1,1)→(2,1)→(2,2)→(2,3)→(2,4)→(3,4);
(1,1)→(1,2)→(2,2)→(2,3)→(3,3)→(3,4);
(1,1)→(1,2)→(1,3)→(2,3)→(3,3)→(3,4).
题意:从端点[1,1]走至端点[n,m],只能向右向下,每个点都带有一个数值,经过的路径数值全异或后等于k时,该路径符合要求。输出符合该条件的路径条数。
思路:1<=n,m<=20,纯dfs复杂度至2^(20+20),Tle,得用折半搜索
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 21;
int mp[N][N],n,m,k,ans;
map<int,int>dp[N][N];
bool check(int x,int y){
if (x<=n&&x>=1&&y<=m&&y>=1) return 1;
else return 0;
}
void dfs1(int x,int y,int sum){
if(x + y - 1 == n){
dp[x][y][sum]++;
return;
}
if(check(x,y+1)) dfs1(x,y+1,sum ^ mp[x][y+1]);
if(check(x+1,y)) dfs1(x+1,y,sum ^ mp[x+1][y]);
}
void dfs2(int x,int y,int sum){
if(x + y - 1 == n){
ans += dp[x][y][sum ^ k ^ mp[x][y]];
return;
}
if(check(x,y-1)) dfs2(x,y-1,sum ^ mp[x][y-1]);
if(check(x-1,y)) dfs2(x-1,y,sum ^ mp[x-1][y]);
}
signed main()
{
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
cin >> mp[i][j];
}
dfs1(1,1,mp[1][1]);
dfs2(n,m,mp[n][m]);
cout << ans << endl;
}