Codeforces Round #498 (Div. 3) F. Xor-Paths(双dfs,会合)

There is a rectangular grid of size n×mn×m. Each cell has a number written on it; the number on the cell (i,ji,j) is ai,jai,j. Your task is to calculate the number of paths from the upper-left cell (1,11,1) to the bottom-right cell (n,mn,m) meeting the following constraints:

  • You can move to the right or to the bottom only. Formally, from the cell (i,ji,j) you may move to the cell (i,j+1i,j+1) or to the cell (i+1,ji+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,11,1) to the cell (n,mn,m) must be equal to kk (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 nn, mm and kk (1≤n,m≤201≤n,m≤20, 0≤k≤10180≤k≤1018) — the height and the width of the grid, and the number kk.

The next nn lines contain mm integers each, the jj-th element in the ii-th line is ai,jai,j(0≤ai,j≤10180≤ai,j≤1018).

Output

Print one integer — the number of paths from (1,11,1) to (n,mn,m) with xor sum equal to kk.

Examples

Input

3 3 11
2 1 5
7 10 0
12 6 4

Output

3

Input

3 4 2
1 3 3 3
0 3 3 2
3 0 1 1

Output

5

Input

3 4 1000000000000000000
1 3 3 3
0 3 3 2
3 0 1 1

Output

0

Note

All the paths from the first example:

  • (1,1)→(2,1)→(3,1)→(3,2)→(3,3)(1,1)→(2,1)→(3,1)→(3,2)→(3,3);
  • (1,1)→(2,1)→(2,2)→(2,3)→(3,3)(1,1)→(2,1)→(2,2)→(2,3)→(3,3);
  • (1,1)→(1,2)→(2,2)→(3,2)→(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)→(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)→(3,2)→(3,3)→(3,4);
  • (1,1)→(2,1)→(2,2)→(2,3)→(2,4)→(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)→(2,2)→(2,3)→(3,3)→(3,4);
  • (1,1)→(1,2)→(1,3)→(2,3)→(3,3)→(3,4)(1,1)→(1,2)→(1,3)→(2,3)→(3,3)→(3,4).

题意:从(1,1)出发,只能往下和往右异或,一定走到(n,m)看看有多少路径可以异或后是等于k的

思路:因为 n m取值范围都是小于等于20的,直接爆搜的话,一定超时;本想用记忆化搜索,写了一下,你要用 map容器 mpp[y][x],记录从(y,x)到(n,m)的所有异或值,下一次再搜到这个点时,直接用,就行了,但是每一次回溯时,都要把上次的结果,(y+1,x)或(y,x+1)中mpp的异或值全部和num[y][x]异或,生成mpp[y][x];我不知道这样可行不可行;

这道题可以用双dfs,两个dfs,从(1,1)到搜到(y,x)且 y+x==max(n,m)用mpp[y][x]记录每一个异或值的个数

另一个从(n,m) 搜到 (y,x)且y + x == max(n,m)+1;

折半dfs搜索

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#include<map>
#define Max 22
#define ll long long
ll num[Max][Max],k,ans;
map<ll,ll>mpp[Max][Max];
int n,m,tt;
// 双端dfs , 一个 从 (1,1)到(i,j)且 i+j==max(n,m)
// 第二个 从(n,m)到 (i,j) 且(i+j)==max(n,m)+1 
void dfs1(int y,int x,ll temp)
{
	if(y+x==tt)
	{
		mpp[y][x][temp]++;      //用map记录搜到点(y,x)处时,值为temp的个数; 
 		return ;
	}
	if(y+1<=n)
		dfs1(y+1,x,temp^num[y+1][x]);
	if(x+1<=m)
		dfs1(y,x+1,temp^num[y][x+1]);
}
void dfs2(int y,int x,ll temp)
{
	if(y+x==tt+1)
	{
		if(y-1>=1)
			ans += mpp[y-1][x][k^temp];
		if(x-1>=1)
			ans += mpp[y][x-1][k^temp];
		return ;
	}
	if(y-1>=1)
		dfs2(y-1,x,temp^num[y-1][x]);
	if(x-1>=1)
		dfs2(y,x-1,temp^num[y][x-1]);
}

int main()
{
	int i,j;
	while(~scanf("%d%d%lld",&n,&m,&k))
	{
		for(i = 1;i<=n;i++)
			for(j = 1;j<=m;j++)
			{
				mpp[i][j].clear();
				scanf("%lld",&num[i][j]);
			}
		ans = 0;
		tt = max(n,m);
		if(1+1<=tt)
		{
			dfs1(1,1,num[1][1]);
			dfs2(n,m,num[n][m]);
		}
		else
		{
			if(num[1][1]==k)
				ans++;
		}
		printf("%lld\n",ans);
	}
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/obsorb_knowledge/article/details/81298425
今日推荐