Find The Operations
Difficulty: Hard

You are given a square grid of size N, with rows numbered from 0 to N - 1 starting from the top and columns numbered from 0 to N - 1 starting from the left.   

A cell (u, v) refers to the cell that is on the u<sup>th</sup> row and the v<sup>th</sup> column. Each cell contains an integer - 0 or 1. You can pick any cell and flip the number in all the cells (including the picked cell) within the Manhattan distance D from the picked cell. A flip here means changing the number from 0 to 1 and vice-versa. The manhattan distance from the cell (u, v) to the cell (x, y) is equal to $|u - x| + |v - y|$ where $|i|$ is the absolute value of i.   

Your mission is to change all values in the grid to zero without using more than N×N flips.

**Input Format**  
The first line of the input contains two integers N and D  separated by a single space.  
Each line in the next N lines contains N integers separated by a single space which are either 0 or 1. the i<sub>th</sub> number on the j<sub>th</sub> line is the number on the cell (i - 1, j - 1) of the grid.

**Constraints**  
1 ≤  N ≤  20  
 0 ≤ D ≤ 40

**Output Format**  
If there is no solution, your output should contain exactly a single string "Impossible" (without quotes). If a solution exists, print out the string "Possible" (without quotes) in the first line of your output. In the second line, print out an integer M which represent the number of operations that you need. Each line in the next M lines should contain a pair of integers separated by a single space representing the cell that you picked for the corresponding operation. Note that if there is more than one solution you can pick any one of them.

**Sample Input:#00**

    3 1
    0 1 0
    1 1 1
    0 1 0

**Sample Output:#00**

    Possible
    1
    1 1

**Sample Input:#01**

    3 2
    1 0 1 
    1 1 0 
    0 0 0 

**Sample Output:#01**

    Impossible

**Explanation**

In the first testcase, we can perform the first operation in the center cell, this will flip all the elements to 0 within 1 manhattan distance.  
In the second testcase, we cannot make it an all 0 matrix under 9 moves. Hence, Impossible. 


Input Format:

Output Format:

Sample Input:

Sample Output:

Python 3 starter code:

Editorial: Find The Operations : Nov 20/20 Editorial
<style id="MathJax_SVG_styles">.MathJax_SVG_Display {text-align: center; margin: 1em 0em; position: relative; display: block!important; text-indent: 0; max-width: none; max-height: none; min-width: 0; min-height: 0; width: 100%}
.MathJax_SVG .MJX-monospace {font-family: monospace}
.MathJax_SVG .MJX-sans-serif {font-family: sans-serif}
.MathJax_SVG {display: inline; font-style: normal; font-weight: normal; line-height: normal; font-size: 100%; font-size-adjust: none; text-indent: 0; text-align: left; text-transform: none; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0; min-height: 0; border: 0; padding: 0; margin: 0}
.MathJax_SVG * {transition: none; -webkit-transition: none; -moz-transition: none; -ms-transition: none; -o-transition: none}
.mjx-svg-href {fill: blue; stroke: blue}
.MathJax_SVG_LineBox {display: table!important}
.MathJax_SVG_LineBox span {display: table-cell!important; width: 10000em!important; min-width: 0; max-width: none; padding: 0; border: 0; margin: 0}
</style><svg style="display: none;"><defs id="MathJax_SVG_glyphs"></defs></svg><p><a href="https://www.hackerrank.com/contests/nov13/challenges/FLIP">Find The Operations</a> <br>
Let's try to modify a 0-1 grid. Problem statement <a href="https://www.hackerrank.com/contests/nov13/challenges/FLIP">here</a>.  </p>

<p><strong>Difficulty Level</strong></p>

<p>Medium-Hard</p>

<p><strong>Required Knowledge</strong></p>

<p>Gaussian Elimination, Linear Algebra</p>

<p><strong>Time Complexity</strong></p>

<p>O(N^2) for each test case</p>

<p><strong>Problem Setter</strong> <br>
<a href="https://www.hackerrank.com/tuananhnb93">Tran Dang Tuan Anh</a>  </p>

<p><strong>Problem Tester</strong> <br>
<a href="https://www.hackerrank.com/cpcs">Peng Cao</a></p>

<p><strong>Approach</strong>
Given N and D <br>
and initial matrix given is M[N][N]. <br>
Construct Matrices A[NXN][NXN] and B[NXN]. Such as <br>
For all A [i][j] i be the index for each value in M, and A[i][j] = 1 if j lies in the given "D" Manhattan distance from i.  </p>

<p>Hence we get the A[][] matrix that contains the information of all the j values that will be flipped, for corresponding i.  </p>

<p>And we fill B[i] with initial values of all i in M[N][N]</p>

<p>Now we know that each element will be flipped only once. It can have a value 0 or 1 initially. So we try to solve by <a href="http://en.wikipedia.org/wiki/Gaussian_elimination">Gaussian Elimination</a> equation Ax=B but instead of subtraction we take ^(XOR) as we don't have to deal with -ve values. </p>

<p>If B[i] ==1 and corresponding all the j's in A[i][j] are 0. It is Impossible to solve. <br>
Also when B[i]== 1 and diagonal A[i][i] =0 we can not flip the value hence Impossible to solve. <br>
For all other cases it is Possible and in the end we are left with a diagonal matrix and the result matrix B. Corresponding to the state where all Elements are 0.</p>

<p>After that we simply count the elements in B[NXN] array and for each index in B (index/N, index%N) is the required index.</p>

<p><strong>Setter's Code</strong> :</p>

<pre><code>#include &lt;cstdio&gt;
#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;vector&gt;
#include &lt;queue&gt;
#include &lt;stack&gt;
#include &lt;set&gt;
#include &lt;map&gt;
#include &lt;cstring&gt;
#include &lt;cstdlib&gt;
#include &lt;cmath&gt;
#include &lt;string&gt;
#include &lt;memory.h&gt;
#include &lt;sstream&gt;
#include &lt;complex&gt;
#include &lt;cassert&gt;

#define REP(i,n) for(int i = 0, _n = (n); i &lt; _n; i++)
#define REPD(i,n) for(int i = (n) - 1; i &gt;= 0; i--)
#define FOR(i,a,b) for (int i = (a), _b = (b); i &lt;= _b; i++)
#define FORD(i,a,b) for (int i = (a), _b = (b); i &gt;= _b; i--)
#define FORN(i,a,b) for(int i=a;i&lt;b;i++)
#define FOREACH(it,c) for (__typeof((c).begin()) it=(c).begin();it!=(c).end();it++)
#define RESET(c,x) memset (c, x, sizeof (c))

#define PI acos(-1)
#define sqr(x) ((x) * (x))
#define PB push_back
#define MP make_pair
#define F first
#define S second
#define Aint(c) (c).begin(), (c).end()
#define SIZE(c) (c).size()

#define DEBUG(x) { cerr &lt;&lt; #x &lt;&lt; " = " &lt;&lt; x &lt;&lt; endl; }
#define PR(a,n) {cerr&lt;&lt;#a&lt;&lt;" = "; FOR(_,1,n) cerr &lt;&lt; a[_] &lt;&lt; ' '; cerr &lt;&lt;endl;}
#define PR0(a,n) {cerr&lt;&lt;#a&lt;&lt;" = ";REP(_,n) cerr &lt;&lt; a[_] &lt;&lt; ' '; cerr &lt;&lt; endl;}
#define LL long long

#define maxn 24

using namespace std;

int Gauss(int n, int a[][maxn * maxn], int b[]) {
    for (int i = 0; i &lt; n; i++) {
        int row = -1;
        for (int j = i; j &lt; n; j++)
            if (a[j][i]) {
                row = j;
                break;
            }

        if (row == -1) continue;

        if (!a[i][i])
            for (int j = 0; j &lt;= n; j++)
                a[i][j] ^= a[row][j];

        for (int k = i; k &lt; n; k++)
        if (k != i &amp;&amp; a[k][i] == 1) {
            for (int j = 0; j &lt;= n; j++)
                a[k][j] ^= a[i][j];
        }
    }

    for (int i = 0; i &lt; n; i++)
        if (a[i][n]) {
            int ok = 0;
            for (int j = 0; j &lt; n; j++)
                if (a[i][j]) {
                    ok = 1;
                    break;
                }
            if (!ok) return 0;
        }

    for (int i = n - 1; i &gt;= 0; i--) {
       if (a[i][i] == 0 &amp;&amp; a[i][n] == 1) return 0;
        if (a[i][i] == 0) b[i] = 0;
        else b[i] = a[i][n];

        if (b[i])
        for (int j = i - 1; j &gt;= 0; j--)
            if (a[j][i] == 1) a[j][n] ^= 1;
    }

    return 1;
}

int n, d, g[maxn][maxn], a[maxn * maxn][maxn * maxn], root[maxn * maxn];

int main() {
    cin &gt;&gt; n &gt;&gt; d;
    for (int i = 0; i &lt; n; i++)
        for (int j = 0; j &lt; n; j++)
            cin &gt;&gt; g[i][j];

    for (int i = 0; i &lt; n; i++)
        for (int j = 0; j &lt; n; j++) {
            int row = i * n + j;

            a[row][n * n] = g[i][j];

            for (int x = 0; x &lt; n; x++)
                for (int y = 0; y &lt; n; y++)
                    if (abs(x - i) + abs(y - j) &lt;= d) {
                       // cerr &lt;&lt; x * n + y &lt;&lt; endl;
                        a[row][x * n + y] = 1;
                    }
        }

    int res = Gauss(n * n, a, root);

    if (!res) cout &lt;&lt; "Impossible" &lt;&lt; endl;
    else {
        cout &lt;&lt; "Possible" &lt;&lt; endl;
        int cnt = 0;
        for (int i = 0; i &lt; n * n; i++)
            cnt += root[i];

        cout &lt;&lt; cnt &lt;&lt; endl;

        for (int i = 0; i &lt; n * n; i++)
            if (root[i]) cout &lt;&lt; i / n &lt;&lt; " " &lt;&lt; i % n &lt;&lt; endl;
    }

    return 0;
}
</code></pre>

<p><strong>Tester's Code</strong></p>

<pre><code>#include &lt;cmath&gt;
#include &lt;cstdio&gt;
#include &lt;vector&gt;
#include &lt;iostream&gt;
#include &lt;algorithm&gt;
using namespace std;

const int N = 402;
int a[N][N],b[N];
vector&lt;int&gt; result;


int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
    int n, d,i,j,k;
    scanf("%d%d",&amp;n,&amp;d);
    for (i = 0; i &lt; n; ++i) {
        for (j = 0; j &lt; n; ++j) {
            scanf("%d",b + i * n + j);
            for (int x = max(i - d, 0); (x &lt; n) &amp;&amp; (x &lt;= i + d); ++x) {
                int dd = x - i;
                if (dd &lt; 0) {
                    dd = -dd;
                }
                dd = d - dd;
                for (int y = max(j - dd, 0); (y &lt; n) &amp;&amp; (y &lt;= j + dd); ++y) {
                    a[i * n + j][x * n + y] = 1;
                }
            }

        }
    }
    int m = n * n;

    for (i = 0; i &lt; m; ++i) {

        for (j = i; j &lt; m; ++j) {
            if (a[j][i]) {
                break;
            }
        }
        if (j &lt; m) {
            if (j != i) {
                // exchange row j and row i
                for (k = 0; k &lt; m; ++k) {
                    int t = a[j][k];
                    a[j][k] = a[i][k];
                    a[i][k] = t;
                }
                k = b[i];
                b[i] = b[j];
                b[j] = k;
            }
            for (j = i + 1; j &lt; m; ++j) {
                if (a[j][i]) {
                    for (int k = i; k &lt; m; ++k) {
                        a[j][k] ^= a[i][k];
                    }
                    b[j] ^= b[i];
                }
            }

        }
    }

    for (i = m - 1; i &gt;= 0; --i) {
        for (j = i + 1; j &lt; m; ++j) {
            b[i] ^= (a[i][j] &amp; b[j]);
        }
        if ((a[i][i] == 0) &amp;&amp; (b[i] != 0)) {
            break;
        }
        if (b[i]) {
            result.push_back(i);
        }
    }
    if (i &lt; 0) {
        puts("Possible");
        printf("%d\n",result.size());
        for (int i = 0; i &lt; result.size(); ++i) {
            printf("%d %d\n",result[i] / n, result[i] % n);
        }

    }
    else {
        puts("Impossible");
    }

    return 0;
}
</code></pre>

Reference solution (C++):
###C++  
```cpp  
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
    
const int N = 402;
int a[N][N],b[N];
vector<int> result;
    
    
int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
    int n, d,i,j,k;
    scanf("%d%d",&n,&d);
    for (i = 0; i < n; ++i) {
        for (j = 0; j < n; ++j) {
            scanf("%d",b + i * n + j);
            for (int x = max(i - d, 0); (x < n) && (x <= i + d); ++x) {
                int dd = x - i;
                if (dd < 0) {
                    dd = -dd;
                }
                dd = d - dd;
                for (int y = max(j - dd, 0); (y < n) && (y <= j + dd); ++y) {
                    a[i * n + j][x * n + y] = 1;
                }
            }
            
        }
    }
    int m = n * n;
    
    for (i = 0; i < m; ++i) {
        
        for (j = i; j < m; ++j) {
            if (a[j][i]) {
                break;
            }
        }
        if (j < m) {
            if (j != i) {
                // exchange row j and row i
                for (k = 0; k < m; ++k) {
                    int t = a[j][k];
                    a[j][k] = a[i][k];
                    a[i][k] = t;
                }
                k = b[i];
                b[i] = b[j];
                b[j] = k;
            }
            for (j = i + 1; j < m; ++j) {
                if (a[j][i]) {
                    for (int k = i; k < m; ++k) {
                        a[j][k] ^= a[i][k];
                    }
                    b[j] ^= b[i];
                }
            }
            
        }
    }
    
    for (i = m - 1; i >= 0; --i) {
        for (j = i + 1; j < m; ++j) {
            b[i] ^= (a[i][j] & b[j]);
        }
        if ((a[i][i] == 0) && (b[i] != 0)) {
            break;
        }
        if (b[i]) {
            result.push_back(i);
        }
    }
    if (i < 0) {
        puts("Possible");
        printf("%d\n",result.size());
        for (int i = 0; i < result.size(); ++i) {
            printf("%d %d\n",result[i] / n, result[i] % n);
        }
        
    }
    else {
        puts("Impossible");
    }
    
    return 0;
}
```