CodeForces-1006F Xor-Paths
有n x m个网格,网格值为a(i,j),从(1,1)走到(n,m),每次只能向右走或者向下走,将经过的格子的值全部异或起来,求走到(n,m)时异或值为k的走法有多少种
输入:
n、m:n x m的网格
k:要求得到的异或值
n行,每行m个:网格a(i,j)的值
输出:从(1,1)走到(n,m),最后异或值为k的走法有多少种
直接从(1,1)深搜到(n,m)会TLE,采用折半搜索:从(1,1)深搜到中点,从终点(n,m)深搜到中点
因为n,m均可取1,所以中点不能取(n+m)/2而要取(n+m+2)/2
另:一开始用vector储存从(1,1)走到中点的值时TLE了,大概是因为遍历vector中元素提高了时间复杂度
因为走到某个x值时其y值一定是固定的,可以直接使用mp[x][price]存(price是走到a[x][y]时得到的异或值)
再有,要判断mp[x][mm]是否为空(mp[x].size()!=0也ac了,emmm),否则会越界访问Runtime error
/*折半搜索*/
/*CodeForces-1006F*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define PI acos(-1.0)
int n,m;
ll k;
map<ll,ll> mp[25];
ll num[25][25];
ll sum;
void dfs1(int x,int y,ll price)
{
if(x+y>(n+m+2)/2) return;
if(x+y==(n+m+2)/2)
{
price=price^num[x][y];
mp[x][price]++;
return;
}
else
{
ll t=price^num[x][y];
dfs1(x+1,y,t);
dfs1(x,y+1,t);
}
}
void dfs2(int x,int y,ll price)
{
if(x+y<(n+m+2)/2) return;
if(x+y==(n+m+2)/2)
{
ll mm=price^k;
if(mp[x].size()!=0)
sum+=mp[x][mm];
return;
}
else
{
ll t=price^num[x][y];
dfs2(x-1,y,t);
dfs2(x,y-1,t);
}
}
int main()
{
scanf("%d%d",&n,&m);
scanf("%I64d",&k);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%I64d",&num[i][j]);
}
}
dfs1(1,1,0);
sum=0;
dfs2(n,m,0);
printf("%I64d\n",sum);
return 0;
}