 Open in App
Not now

# Count of Possible paths of given Matrix having Bitwise XOR equal to K

• Difficulty Level : Hard
• Last Updated : 24 Jan, 2023

Given an N*M (N + M ≤ 40)matrix mat[][], each cell has some value ranging from 0 to 1018 and an integer  K. Find the count of all possible paths such that bitwise XOR of elements in a path is equal to K. Movement is allowed only in the right and downward direction.

Examples:

Input: N = 3, M = 4, K= 2
mat[][] = { {1, 3, 3, 3},
{0, 3, 3, 2},
{3, 0, 1, 1} }
Output: 5
Explanation: All possible paths are:
(1,1)→(2,1)→(2,2)→(3,2)→(3,3)→(3,4) =  1^0 ^3^0^1^1 = 2
(1,1)→(2,1)→(3,1)→(3,2)→(3,3)→(3,4) = 1^0^3^0^1^1 = 2
(1,1)→(2,1)→(2,2)→(2,3)→(2,4)→(3,4) = 1^0^3^3^2^1 =2
(1,1)→(1,2)→(1,3)→(2,3)→(3,3)→(3,4) = 1^3^3^3^1^1 =2
(1,1)→(1,2)→(2,2)→(2,3)→(3,3)→(3,4) =  1^3^3^3^1^1 =2

Input: N = 3, M = 3, K =11
mat[][] = { {2, 1, 5},
{7, 10, 0},
{12, 6, 4} }
Output: 3
Explanation:All possible paths are:
(1,1)→(2,1)→(3,1)→(3,2)→(3,3) = 2 ^ 7 ^12 ^ 6 ^4 =11
(1,1)→(2,1)→(2,2)→(2,3)→(3,3) = 2 ^ 7 ^ 10 ^ 0 ^4 =11
(1,1)→(1,2)→(2,2)→(3,2)→(3,3) = 2^1^10^ 6 ^ 4 = 11

Naive Approach: The simple approach is to travel all possible paths and check if the XOR of that path is equal to K or not. In this, use backtracking as at any given cell there will be two choices either to go right or down and this would become two recursive statements in backtracking solution.

Below is the implementation of the above approach :

## C++

 `// C++ code to implement the above approach` `#include ` `using` `namespace` `std;`   `#define ll long long int` `ll n, m, k;` `vector> mat;`   `// Backtracking to find the path count` `void` `backtracking(ll i, ll j, ll zor, ll &ans)` `{` `    ``// If the bottom-right cell is reached` `    ``if` `(i == n - 1 && j == m - 1) {` `        `  `        ``// If XOR value is k` `        ``if` `(zor == k)` `            ``ans++;` `        ``return``;` `    ``}`   `    ``// Move rightwards` `    ``if` `(j + 1 < m)` `        ``backtracking(i, j + 1, ` `                     ``zor ^ mat[i][j + 1], ` `                     ``ans);` `  `  `    ``// Move downwards` `    ``if` `(i + 1 < n)` `        ``backtracking(i + 1, j, ` `                     ``zor ^ mat[i + 1][j], ` `                     ``ans);` `}`   `// Function to calculate all possible paths` `int` `countPaths(``int` `N, ``int` `M, ``int` `K)` `{` `    ``ll ans = 0;` `    ``n = N; m = M; k = K;` `    ``if` `(N == 1 && M == 1 ` `        ``&& mat == K) {` `        ``return` `1;` `    ``}` `  `  `    ``// Calling the backtracking function` `    ``backtracking(0, 0, mat, ans);` `    ``return` `ans;` `}`   `// Driver Code` `int` `main()` `{` `    ``int` `N = 3, M = 3, K = 11;` `    ``mat = { {2, 1, 5}, {7, 10, 0}, ` `            ``{12, 6, 4} };`   `    ``// Function call` `    ``int` `ans = countPaths(N, M, K);` `    ``cout << ans << ``"\n"``;` `    ``return` `0;` `}`

## Java

 `// Java code to implement the above approach` `import` `java.util.*;`   `class` `GFG{`   `  ``static` `int`  `n, m, k , ans;` `  ``static` `int` `[][]mat;`   `  ``// Backtracking to find the path count` `  ``static` `void` `backtracking(``int` `i, ``int` `j, ``int` `zor)` `  ``{` `    ``// If the bottom-right ceint is reached` `    ``if` `(i == n - ``1` `&& j == m - ``1``) {`   `      ``// If XOR value is k` `      ``if` `(zor == k)` `        ``ans++;` `      ``return``;` `    ``}`   `    ``// Move rightwards` `    ``if` `(j + ``1` `< m)` `      ``backtracking(i, j + ``1``, ` `                   ``zor ^ mat[i][j + ``1``]);`   `    ``// Move downwards` `    ``if` `(i + ``1` `< n)` `      ``backtracking(i + ``1``, j, ` `                   ``zor ^ mat[i + ``1``][j]);` `  ``}`   `  ``// Function to calculate all possible paths` `  ``static` `int` `countPaths(``int` `N, ``int` `M, ``int` `K)` `  ``{` `    ``ans = ``0``;` `    ``n = N; m = M; k = K;` `    ``if` `(N == ``1` `&& M == ``1` `        ``&& mat[``0``][``0``] == K) {` `      ``return` `1``;` `    ``}`   `    ``// Calling the backtracking function` `    ``backtracking(``0``, ``0``, mat[``0``][``0``]);` `    ``return` `ans;` `  ``}`   `  ``// Driver Code` `  ``public` `static` `void` `main(String[] args)` `  ``{` `    ``int` `N = ``3``, M = ``3``, K = ``11``;` `    ``mat = ``new` `int``[][]{ {``2``, ``1``, ``5``}, {``7``, ``10``, ``0``}, ` `                      ``{``12``, ``6``, ``4``} };`   `    ``// Function call` `    ``int` `ans = countPaths(N, M, K);` `    ``System.out.print(ans+ ``"\n"``);` `  ``}` `}`   `// This code is contributed by 29AjayKumar`

## Python3

 `# Python program to find maximum sum in Binary Tree` `mat ``=` `[[``0` `for` `i ``in` `range``(``2``)]``for` `j ``in` `range``(``2``)]` `n,m,k,ans ``=` `0``,``0``,``0``,``0`   `# Backtracking to find the path count` `def` `backtracking(i, j, zor):`   `    ``global` `ans`   `    ``# If the bottom-right ceis reached` `    ``if` `(i ``=``=` `n ``-` `1` `and` `j ``=``=` `m ``-` `1``):`   `        ``# If XOR value is k` `        ``if` `(zor ``=``=` `k):` `            ``ans ``+``=` `1` `        ``return`   `    ``# Move rightwards` `    ``if` `(j ``+` `1` `< m):` `        ``backtracking(i, j ``+` `1``,zor ^ mat[i][j ``+` `1``])`   `    ``# Move downwards` `    ``if` `(i ``+` `1` `< n):` `        ``backtracking(i ``+` `1``, j,zor ^ mat[i ``+` `1``][j])`   `# Function to calculate all possible paths` `def` `countPaths(N, M, K):`   `    ``global` `n,m,k,ans`   `    ``ans ``=` `0` `    ``n,m,k ``=` `N,M,K` `    ``if` `(N ``=``=` `1` `and` `M ``=``=` `1` `and` `mat[``0``][``0``] ``=``=` `K):` `        ``return` `1`   `    ``# Calling the backtracking function` `    ``backtracking(``0``, ``0``, mat[``0``][``0``])` `    ``return` `ans`     `# Driver Code` `N,M,K ``=` `3``,``3``,``11` `mat ``=` `[ [``2``, ``1``, ``5``], [``7``, ``10``, ``0``],` `                    ``[``12``, ``6``, ``4``]]`   `# Function call` `anss ``=` `countPaths(N, M, K)` `print``(anss)`   `# This code is contributed by shinjanpatra`

## C#

 `// C# code to implement the above approach` `using` `System;`   `class` `GFG{`   `  ``static` `int`  `n, m, k, ans;`   `  ``// Backtracking to find the path count` `  ``static` `void` `backtracking(``int` `i, ``int` `j, ``int` `zor, ``int` `[,]mat)` `  ``{` `    ``// If the bottom-right ceint is reached` `    ``if` `(i == n - 1 && j == m - 1) {`   `      ``// If XOR value is k` `      ``if` `(zor == k)` `        ``ans++;` `      ``return``;` `    ``}`   `    ``// Move rightwards` `    ``if` `(j + 1 < m)` `      ``backtracking(i, j + 1, ` `                   ``zor ^ mat[i, j + 1], mat);`   `    ``// Move downwards` `    ``if` `(i + 1 < n)` `      ``backtracking(i + 1, j, ` `                   ``zor ^ mat[i + 1, j], mat);` `  ``}`   `  ``// Function to calculate all possible paths` `  ``static` `int` `countPaths(``int` `N, ``int` `M, ``int` `K, ``int` `[,]mat)` `  ``{` `    ``ans = 0;` `    ``n = N; m = M; k = K;` `    ``if` `(N == 1 && M == 1 ` `        ``&& mat[0, 0] == K) {` `      ``return` `1;` `    ``}`   `    ``// Calling the backtracking function` `    ``backtracking(0, 0, mat[0, 0], mat);` `    ``return` `ans;` `  ``}`   `  ``// Driver Code` `  ``public` `static` `void` `Main()` `  ``{` `    ``int` `N = 3, M = 3, K = 11;` `    ``int` `[,]mat = { {2, 1, 5}, {7, 10, 0}, ` `                      ``{12, 6, 4} };`   `    ``// Function call` `    ``int` `ans = countPaths(N, M, K, mat);` `    ``Console.Write(ans+ ``"\n"``);` `  ``}` `}`   `// This code is contributed by Samim Hossain Mondal.`

## Javascript

 ``

Output

```3
```

Time Complexity: O(2X * X) where X = (N + M – 2)
Auxiliary Space: O(1)

Why simply  Backtracking would fail here?
The number of moves required to move from (1, 1) to (N, M) will be equal to (N+M-2). Now, using a recursive backtracking solution It will take O(2(N+M-2)) time to iterate over all the paths of this length and check if each path is having XOR equal to K or not. For higher values of (N+M) this algorithm becomes very time consuming as the value reaches close to the constraint provided here.

Efficient Approach: Using Meet in The Middle Algorithm split the number of steps and make (N + M – 2)/2 in the first half, rest steps in the next half. Follow the steps mentioned below to solve the problem:

• And combine the answers of the two solutions, which is basically the standard idea of the Meet in the Middle Algorithm.
• Split this mask of n+m−2 bits into two parts, mid=(n+m−2)/2 bits and (n+m−2)−mid bits.
• For The Left Part:
• Perform recursive backtracking starting from the cell (1,1) and to the bottom and maintain xor of the path for mid steps. after mid steps, we have the index position i.e. (i,j) and the xor value up to this point, and calculate how many such triplets exits {zor, i,j}
• For The Right Part:
• Perform recursive backtracking starting from the cell (N, M) and to the left or to the upwards and maintain xor of the path for
(N+M-2) – mid -1 steps.
• after mid steps in, the index position i.e. (i,j) is found and the xor value up to this point, and calculate how many such triplets exits {zor, i,j}
• After writing code for both parts now traverse the triplets of the second part and check if in one step i.e (i-1,j) or (j-1, i) we have a triplet having xor K in triplets of the left part.

Below is the implementation of the above approach:

## C++14

 `// C++ code to implement the above approach` `#include ` `using` `namespace` `std;`   `#define ll long long int` `ll n, m, k;` `vector> a;` `ll cnt1 = 0, cnt2 = 0;` `map >, ll> mp1, mp2;`   `// Backtracking function for the left part` `void` `part1(ll i, ll j, ll cnt, ll zor)` `{` `    ``if` `(cnt <= 0) {` `        `  `        ``// Count the number of triplets` `        ``mp1[{ zor, { i, j } }]++;` `        ``return``;` `    ``}`   `    ``// Move rightwards` `    ``if` `(j + 1 < m) {` `        ``part1(i, j + 1, cnt - 1, ` `              ``zor ^ a[i][j + 1]);` `    ``}` `  `  `    ``// Move downwards` `    ``if` `(i + 1 < n)` `        ``part1(i + 1, j, cnt - 1, ` `              ``zor ^ a[i + 1][j]);` `}`   `// Backtracking function for the right part` `void` `part2(ll i, ll j, ll cnt, ll zor)` `{` `    ``if` `(cnt <= 0) {` `        `  `        ``// Count the number of triplets` `        ``mp2[{ zor, { i, j } }]++;` `        ``return``;` `    ``}`   `    ``// Move leftwards` `    ``if` `(j - 1 >= 0) {` `        ``part2(i, j - 1, cnt - 1, ` `              ``zor ^ a[i][j - 1]);` `    ``}` `  `  `    ``// Move upwards` `    ``if` `(i - 1 >= 0)` `        ``part2(i - 1, j, cnt - 1, ` `              ``zor ^ a[i - 1][j]);` `}`   `// Function to count the paths with xor K` `int` `countPaths(``int` `N, ``int` `M, ``int` `K)` `{` `    ``ll ans = 0;` `    ``n = N; m = M; k = K;` `    `  `    ``// Number of steps for left part` `    ``cnt1 = (n + m - 2) / 2;`   `    ``// NUmber of steps for right part` `    ``cnt2 = (n + m - 2) - cnt1;`   `    ``// number of steps in both parts are 0` `    ``if` `(n == 1 && m == 1 && a == k) {` `        ``return` `1;` `    ``}`   `    ``// Calling the recursive function` `    ``// for the left and right part` `    ``part1(0, 0, cnt1, a);` `    ``part2(n - 1, m - 1, cnt2 - 1, ` `          ``a[n - 1][m - 1]);`   `    ``// mp2 contains triplet of right part so` `    ``// traverse the triplets of right part` `    ``for` `(``auto` `i : mp2) {`   `        ``// Extracting all elements ` `        ``// from the triplet` `        ``ll zor = i.first.first;` `        ``ll idx = i.first.second.first;` `        ``ll j = i.first.second.second;` `        ``ll cnt = i.second;`   `        ``// XOR OF RIGHT SIDE IS zor ,` `        ``// then Xor of left side` `        ``// must be zor^k such that Xor` `        ``// of the total path is K` `        ``ll required = k ^ zor;`   `        ``// Checking if one index to the left` `        ``// are left triplet as how many paths` `        ``if` `((idx - 1) >= 0` `            ``&& mp1.find({ required, ` `                         ``{ idx - 1, j } })` `                   ``!= mp1.end()) {`   `            ``// Total path would be paths` `            ``// in left * paths in right` `            ``ans += (cnt` `                    ``* mp1[{ required, ` `                           ``{ idx - 1, j } }]);` `        ``}`   `        ``// Checking if one index upwards` `        ``// are left triplet as how many paths` `        ``if` `((j - 1) >= 0` `            ``&& mp1.find({ required, ` `                         ``{ idx, j - 1 } })` `                   ``!= mp1.end()) {` `            `  `            ``// Total path would be paths` `            ``// in left * paths in right` `            ``ans += (cnt` `                    ``* mp1[{ required, ` `                           ``{ idx, j - 1 } }]);` `        ``}` `    ``}` `    ``return` `ans;` `}`   `// Driver Code` `int` `main()` `{` `    ``int` `N = 3, M = 3, K = 11;` `    ``a = { {2, 1, 5}, {7, 10, 0}, ` `            ``{12, 6, 4} };` `    `  `    ``int` `ans = countPaths(N, M, K);` `    ``cout << ans;` `    ``return` `0;` `}`

## Python3

 `from` `typing ``import` `List``, ``Tuple` `from` `collections ``import` `defaultdict`   `def` `count_paths(n: ``int``, m: ``int``, k: ``int``, a: ``List``[``List``[``int``]]) ``-``> ``int``:` `    ``# cnt1: number of steps in left part` `    ``# cnt2: number of steps in right part` `    ``cnt1 ``=` `(n ``+` `m ``-` `2``) ``/``/` `2` `    ``cnt2 ``=` `(n ``+` `m ``-` `2``) ``-` `cnt1` `    `  `    ``# Edge case: matrix is 1x1 and the only element is k` `    ``if` `n ``=``=` `1` `and` `m ``=``=` `1` `and` `a[``0``][``0``] ``=``=` `k:` `        ``return` `1`   `    ``mp1 ``=` `defaultdict(``int``) ``# left part` `    ``mp2 ``=` `defaultdict(``int``) ``# right part`   `    ``# Recursive function for left part` `    ``def` `part1(i: ``int``, j: ``int``, cnt: ``int``, zor: ``int``) ``-``> ``None``:` `        ``if` `cnt <``=` `0``:` `            ``# Count the number of triplets` `            ``mp1[(zor, (i, j))] ``+``=` `1` `            ``return` `        `  `        ``# Move rightwards` `        ``if` `j ``+` `1` `< m:` `            ``part1(i, j ``+` `1``, cnt ``-` `1``, zor ^ a[i][j ``+` `1``])` `            `  `        ``# Move downwards` `        ``if` `i ``+` `1` `< n:` `            ``part1(i ``+` `1``, j, cnt ``-` `1``, zor ^ a[i ``+` `1``][j])`   `    ``# Recursive function for right part` `    ``def` `part2(i: ``int``, j: ``int``, cnt: ``int``, zor: ``int``) ``-``> ``None``:` `        ``if` `cnt <``=` `0``:` `            ``# Count the number of triplets` `            ``mp2[(zor, (i, j))] ``+``=` `1` `            ``return` `        `  `        ``# Move leftwards` `        ``if` `j ``-` `1` `>``=` `0``:` `            ``part2(i, j ``-` `1``, cnt ``-` `1``, zor ^ a[i][j ``-` `1``])` `            `  `        ``# Move upwards` `        ``if` `i ``-` `1` `>``=` `0``:` `            ``part2(i ``-` `1``, j, cnt ``-` `1``, zor ^ a[i ``-` `1``][j])`   `    ``# Call the recursive functions for left and right parts` `    ``part1(``0``, ``0``, cnt1, a[``0``][``0``])` `    ``part2(n ``-` `1``, m ``-` `1``, cnt2 ``-` `1``, a[n ``-` `1``][m ``-` `1``])`   `    ``ans ``=` `0` `    ``# Iterate through the triplets in the right part` `    ``for` `zor, (idx, j), cnt ``in` `mp2.items():` `        ``# XOR of right side is zor, XOR of left side must be zor^k` `        ``# such that XOR of the total path is K` `        ``required ``=` `k ^ zor` `        `  `        ``# Check if there is a left triplet one index to the left` `        ``if` `idx ``-` `1` `>``=` `0` `and` `(required, (idx ``-` `1``, j)) ``in` `mp1:` `            ``# Total path is paths in left * paths in right` `            ``ans ``+``=` `cnt ``*` `mp1[(required, (idx ``-` `1``, j))]` `        `  `        ``# Check if there is a left triplet one index upwards` `        ``if` `j ``-` `1` `>``=` `0` `and` `(required, (idx, j ``-` `1``)) ``in` `mp1:`

Output

`3`

Time Complexity: O(X * 2X) where X = (N + M – 2)/2
Auxiliary Space: O(N + M)

My Personal Notes arrow_drop_up
Related Articles