Codeforces#498F. Xor-Paths(折半搜索)

time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

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

Copy

3 3 112 1 57 10 012 6 4

output

Copy

3

input

Copy

3 4 21 3 3 30 3 3 23 0 1 1

output

Copy

5

input

Copy

3 4 10000000000000000001 3 3 30 3 3 23 0 1 1

output

Copy

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$的有几条

昨晚前五题都1A之后有点上天qwq。。想了很久才发现这是个思博题不过没时间写了qwq。

考虑如果直接dfs的话是$2^{n + m}$

然后meet in the middle 一下就好了

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
#define MP(x, y) make_pair(x, y)
#define Pair pair<int, int>
#define int long long
using namespace std;
const int MAXN  = 2 * 1e5 + 10, INF = 1e9 + 10;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < ‘0‘ || c > ‘9‘) {if(c == ‘-‘) f = -1; c = getchar();}
    while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar();
    return x * f;
}
int N, M, K;
int a[21][21];
cc_hash_table<int, int> mp[21];
int dfs(int x, int y, int now) {
    if(x < 1 || x > N || y < 1 || y > M) return 0;
    if(x + y == (N + M + 2) / 2) return mp[x][now ^ a[x][y]];
    int ans = 0;
    ans += dfs(x - 1, y, now ^ a[x - 1][y]);
    ans += dfs(x, y - 1, now ^ a[x][y - 1]);
    return ans;
}
void fuck(int x, int y, int now) {
    if(x < 1 || x > N || y < 1 || y > M) return ;
    if(x + y == (N + M + 2) / 2) {mp[x][now]++; return ;}
    fuck(x + 1, y, now ^ a[x + 1][y]);
    fuck(x, y + 1, now ^ a[x][y + 1]);
}
main() {
#ifdef WIN32
    freopen("a.in", "r", stdin);
#endif
    N = read(); M = read(); K = read();
    for(int i = 1; i <= N; i++)
        for(int j = 1; j <= M; j++)
            a[i][j] = read();
    fuck(1, 1, a[1][1]);
    printf("%lld", dfs(N, M, K ^ a[N][M]));
}
/*
1 1 1000000000000000000
1000000000000000000
*/

原文地址:https://www.cnblogs.com/zwfymqz/p/9323274.html

时间: 2024-10-02 10:39:54

Codeforces#498F. Xor-Paths(折半搜索)的相关文章

codeforces 880E. Maximum Subsequence(折半搜索+双指针)

E. Maximum Subsequence time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output You are given an array a consisting of n integers, and additionally an integer m. You have to choose some sequence of

Codeforces 14D Two Paths 树的直径

题目链接:点击打开链接 题意:给定一棵树 找2条点不重复的路径,使得两路径的长度乘积最大 思路: 1.为了保证点不重复,在图中删去一条边,枚举这条删边 2.这样得到了2个树,在各自的树中找最长链,即树的直径,然后相乘即可 #include<stdio.h> #include<iostream> #include<string.h> #include<set> #include<vector> #include<map> #includ

E. Anya and Cubes (CF #297 (Div. 2) 折半搜索)

E. Anya and Cubes time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Anya loves to fold and stick. Today she decided to do just that. Anya has n cubes lying in a line and numbered from 1 to n

算法复习——哈希表+折半搜索(poj2549)

搬讲义~搬讲义~ 折半搜索感觉每次都是打暴力时用的啊2333,主要是用于降次··当复杂度为指数级别时用折半可以减少大量复杂度··其实专门考折半的例题并不多···一般都是中途的一个小优化··· 然后折半搜索常常与哈希表一起使用··尤其是遇到方程类的问题时··· 哈希表就不说了吧···毕竟比较简单···不懂得看下面题的代码就行了,一道折半与哈希表联合运用的经典方程模型题··· Description Given S, a set of integers, find the largest d suc

FZU 2178 礼物分配 (折半搜索+二分)

题目地址:FZU 2178 由于n最大是30,一次全搜的话妥妥的超时,那么可以采用折半搜索.分成相同的两份,对左边的一堆进行预处理,然后再处理右堆,每一次都对左堆进行二分,找最接近的.由于两个人取的不能相差多于1个,所以要对每个个数分开存储.并排序,排序是为了后边的二分. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <

位运算符 优先级 折半搜索

看编程珠玑,深知二分搜索的用处之大,自己写了一遍,竟然出了死循环.代码如下: 1 int bsearch(int *data, int val,int left, int right) 2 { 3 if(left <= right) 4 { 5 int mid = left + (right-left)>>1; 6 if(data[mid]==val) 7 return mid; 8 else if(data[mid]<val) 9 return bsearch(data,val,

【bzoj4800】[Ceoi2015]Ice Hockey World Championship 折半搜索

题目描述 有n个物品,m块钱,给定每个物品的价格,求买物品的方案数. 输入 第一行两个数n,m代表物品数量及钱数 第二行n个数,代表每个物品的价格 n<=40,m<=10^18 输出 一行一个数表示购买的方案数 (想怎么买就怎么买,当然不买也算一种) 样例输入 5 1000 100 1500 500 500 1000 样例输出 8 题解 裸的折半搜索meet-in-the-middle 由于直接爆搜肯定会TLE,考虑把整个序列分成左右两部分,对于每部分求出它所有可以消耗钱数的方案.然后考虑左右

折半搜索+状态压缩【P3067】 [USACO12OPEN]平衡的奶牛群Balanced Cow S…

Description 给n个数,从中任意选出一些数,使这些数能分成和相等的两组. 求有多少种选数的方案. Input 第\(1\)行:一个整数\(N\) 第\(2\)到\(N+1\)行,包含一个整数\(m_i\) Output 一行:平衡的集合的个数. 看到题的一瞬间数据范围? \(N \leq 20?\)状压! 明显直接做过不去,选择折半搜索. 折半搜索的话会有三种情况 一.选择当前位置 二.选择当前位置,给第一组. 三.选择当前位置,给第二组. 然后直接跑折半搜索+状压即可. 存储类似链式

CF1221G Graph And Numbers(折半搜索+图论)

答案=总数-无0-无1-无2+无01+无02+无12-无012 直接详细讲无0和无2 无0为 01和11,无2为01和00,显然二者方案数相同,以下考虑无0 考虑折半搜索,后半段搜索,二进制点权0的位置,保证后半段构成的无0边的基础上 可以得出一个S集合,表示集合内的点随意选择,不在集合内的点只能为1 再搜索前半段,同后半段搜索,得出一个集合T里面的点权为0,则T的贡献为满足\(T\subseteq S\)的S的个数,这个子集和一下即可 原文地址:https://www.cnblogs.com/

折半搜索

折半搜索 (meet in the middle) /* reference: translation: solution: trigger: note: * date: 2019.09.04 */ #include<bits/stdc++.h> using namespace std; #define int long long #define rep(i,a,b) for(int i=a;i<=b;++i) #define dwn(i,a,b) for(int i=a;i>=b