【折半搜索 && 左上到右下异或等于 k 的方案数】Codeforces Round #498 (Div. 3) F. Xor-Paths

Step1 Problem:

给你 n*m 的矩阵,从 (1, 1) 到 (n, m) 只能往下和往右走,路径上的数异或起来等于 k 的路径数。
数据范围:
1<=n, m <= 20. 0 <= k <= 1e18. 0 <= a[i][j] <= 1e18.

Step2 Ideas:

n, m 很小,我特别打了个表,从 (1, 1) 到 (11, 11) 的路径方案数 = 184756。
所以我们可以折半搜索:
为什么选择到 (n+m+2)/2 而不是 (n+m-2)/2,因为 (n+m-2)/2 矩阵太小的话,就没有满足条件的点。
第一遍搜索:从 (1, 1) 到 (n+m+2)/2(包含) 的格子 每个格子构成 sum 的路径方案数存起来。
第二遍搜索:从 (n, m) 到 (n+m+2)/2(不包含) 的格子 异或 k 构成 sum ,将之前构成 sum 存起来的方案数的 和为结果。

Step3 Code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n, m;
ll a[25][25];
map<ll, ll> vis[25];
void dfs1(int u, int v, ll sum)//求 (1, 1) 到 (n+m+2)/2 构成 sum 的路径方案数
{
    if(u+v == (n+m+2)/2) {
        vis[u][sum]++;
        return ;
    }
    if(u <= n)
    dfs1(u+1, v, sum^a[u+1][v]);
    if(v <= m)
    dfs1(u, v+1, sum^a[u][v+1]);
}
ll ans;
void dfs2(int u, int v, ll sum)//(n, m) 到 (n+m+2)/2
{
    if(u+v == (n+m+2)/2) {//构成 sum 就加起来。
        ans += vis[u][sum];
        return ;
    }
    if(u-1 >= 1)
        dfs2(u-1, v, sum^a[u][v]);
    if(v-1 >= 1)
        dfs2(u, v-1, sum^a[u][v]);
}
int main()
{
    ll k;
    scanf("%d %d %lld", &n, &m, &k);
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            scanf("%lld", &a[i][j]);
        }
    }
    dfs1(1, 1, a[1][1]);
    ans = 0;
    dfs2(n, m, k);//需要异或 k
    printf("%lld\n", ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值