Codeforces1006F-Xor-Paths-折半搜索

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

题意:传送门

 原题目描述在最下面。
 题目大意就是给你一个n*m的矩阵,每个点都有权值。问你从点[1, 1]走到[n, m]路径上所有点权异或和为k的路径有多少种。注意只能向下和向右走。

思路:

 大佬说这题暴力就行了。然而我最暴力的搜索方法却超时了。
 这才了解到原来大佬的暴力是折半搜索。

 折半搜索就是把最暴力从[1, 1]搜索到[n, m]的搜索方法,改成,从[1, 1]搜索到中间一个过程,再从[n, m]搜索到中间那个过程。这样的两次搜索,复杂度降低了居多。

 我选取的中间过程是一条斜对角线的平行线:i + j = (n + m)/2 + 1.
 正向搜索过程中用一个map记录搜索到低i行异或和值为x的数量。
 反向搜索过程就是计数了。

 (我测试了一下,折半搜索的时间复杂度大概在2e6左右,逃~

AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5+7;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
int n, m;
LL k, ans, ar[25][25];
unordered_map<LL, LL> cnt[N];
void dfs1(int i, int j, LL val){
  if(i > n || j > m || i < 1 || j < 1)return;
  val ^= ar[i][j];
  if(i + j == (m + n) / 2 + 1){
    //printf("%d %d %lld\n", i,j,val);
    cnt[i][val]++;
    return;
  }
  dfs1(i, j + 1, val);
  dfs1(i + 1, j, val);
}
void dfs2(int i, int j, LL val){
  if(i > n || j > m || i < 1 || j < 1)return;
  if(i + j == (m + n) / 2 + 1){
    ans += cnt[i][k ^ val];
    return;
  }
  val ^= ar[i][j];
  dfs2(i - 1, j, val);
  dfs2(i, j - 1, val);
}
int main(int argc, char const *argv[]){
  while(~scanf("%d%d%lld", &n, &m, &k)){
    for(int i = 1; i <= n; ++i){
       cnt[i].clear();
      for(int j = 1; j <= m; ++j){
        scanf("%lld", &ar[i][j]);
      }
    }
    ans = 0;
    dfs1(1, 1, 0);
    dfs2(n, m, 0);
    printf("%lld\n", ans);
  }  
  return 0;
}


题目描述:

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值