Codeforces Round #498 (Div. 3) F. Xor-Paths(折半搜索
链接
题意:问从1,1到n,m有多少条异或值为k的路径。
解析:
直接暴力为2^40 用折半搜索会降到2^21,
我们只需记录达到中间值x+y==(n+m+2)/2的异或值,反向搜索的时候捕获这个值即可,
需要注意的是中间点被异或了两次,所以要再异或一次
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
#define inf 2099999999
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep1(i,a,b) for(int i=a;i>=b;i--)
const int N=20+10;
ll arr[N][N];
map<ll,ll>mp[N][N];
ll n ,m ,k,ans=0;
void dfs_pre(ll x,ll y ,ll num)
{
if(x+y==(n+m+2)/2)
{
mp[x][y][num]++;
return ;
}
if(x<n) dfs_pre(x+1,y,num^arr[x+1][y]);
if(y<m) dfs_pre(x,y+1,num^arr[x][y+1]);
}
void dfs(ll x,ll y ,ll num)
{
if(x+y == (n+m+2)/2)
{
ans+=mp[x][y][num^k^arr[x][y]];//由于中间点被异或了两次
//这里要异或回去
return ;
}
if(x>1) dfs(x-1,y,num^arr[x-1][y]);
if(y>1) dfs(x,y-1,num^arr[x][y-1]);
}
int main()
{
#ifdef LOCAL_DEFINE
freopen("D://rush.txt", "r", stdin);
#endif
ios::sync_with_stdio(false),cin.tie(0);
cin>>n>>m>>k;
ans=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
cin>>arr[i][j];
}
dfs_pre(1,1,arr[1][1]);
dfs(n,m,arr[n][m]);
cout<<ans<<endl;
}