1. Abridged Problem Statement  
Given an H×W binary matrix A, we define an (H−1)×(W−1) fingerprint B by  
 B[i][j] = A[i][j] + A[i+1][j] + A[i][j+1] + A[i+1][j+1].  
You are given H, W (≤300) and the matrix B (entries 0…4). Reconstruct any A that matches B or report CORRUPT if none exists.

2. Detailed Editorial  

Overview  
We need to recover the full H×W matrix A of 0/1 entries given all its overlapping 2×2 sums. A direct brute‐force over 2^(H×W) is impossible. Instead we observe that once we fix the first row and first column of A, every other entry is determined uniquely by the fingerprint equations. We then only need to check that each computed entry is 0 or 1; if a bad value (outside {0,1}) arises, that forbids certain assignments of the row/column variables. These forbidden pairs translate naturally into 2‐SAT clauses.

Step 1: Variables  
Let r[j] = A[0][j] for j=1…W−1,  
    c[i] = A[i][0] for i=1…H−1,  
and also we try both possibilities for A[0][0] = 0 or 1.  
In total there are (H−1)+(W−1) Boolean variables.

Step 2: Propagation Formula  
Define a helper array δ so that for i,j≥1,  
 δ[i][j] = B[i−1][j−1] − δ[i−1][j] − δ[i][j−1] − δ[i−1][j−1].  
One can show that the true A[i][j] is  
 A[i][j] = δ[i][j]  
  + ( (j even) ? r[j] : −r[j] )  
  + ( (i even) ? c[i] : −c[i] )  
(with all indices 0‐based). This is just unwinding the 2×2 sum equations.

Step 3: 2‐SAT Constraints  
For each cell (i,j) with i,j≥1 we compute  
 val = δ[i][j] ± r[j] ± c[i]  
according to the parities. If val ∉ {0,1}, then that particular combination  
(r[j], c[i]) = (v_row, v_col) is impossible. A forbidden pair is a clause  
 ¬(r[j]=v_row ∧ c[i]=v_col)  
which in 2‐SAT form is (r[j]≠v_row) ∨ (c[i]≠v_col). We add the two implications accordingly.

Step 4: Solve and Reconstruct  
We build a 2‐SAT instance with N=(H−1)+(W−1) variables and O(HW) clauses. We run Kosaraju or Tarjan SCC in O(N+number_of_clauses). Try A[0][0]=0 or 1; if satisfiable, read off r[], c[], rebuild A fully and output. Otherwise print CORRUPT.

Complexity: O(H W) time and memory, with constant‐factor for SCC.
3. C++ Solution
```cpp
#include <bits/stdc++.h>
// #include <coding_library/graph/two_sat.hpp>

using namespace std;

template<typename T1, typename T2>
ostream& operator<<(ostream& out, const pair<T1, T2>& x) {
    return out << x.first << ' ' << x.second;
}

template<typename T1, typename T2>
istream& operator>>(istream& in, pair<T1, T2>& x) {
    return in >> x.first >> x.second;
}

template<typename T>
istream& operator>>(istream& in, vector<T>& a) {
    for(auto& x: a) {
        in >> x;
    }
    return in;
};

template<typename T>
ostream& operator<<(ostream& out, const vector<T>& a) {
    for(auto x: a) {
        out << x << ' ';
    }
    return out;
};

class TwoSat {
  private:
    vector<bool> visited;

    void dfs1(int u) {
        visited[u] = true;
        for(int v: adj[u]) {
            if(!visited[v]) {
                dfs1(v);
            }
        }

        top_sort.push_back(u);
    }

    void dfs2(int u) {
        for(int v: radj[u]) {
            if(comp[v] == -1) {
                comp[v] = comp[u];
                dfs2(v);
            }
        }
    }

  public:
    int n;
    vector<vector<int>> adj, radj;
    vector<int> comp, comp_ids, top_sort;

    TwoSat() {}
    TwoSat(int _n) { init(_n); }

    void init(int _n) {
        n = _n;
        comp_ids.clear();
        top_sort.clear();
        adj.assign(2 * n, {});
        radj.assign(2 * n, {});
    }

    void add_implication(int u, int v, bool neg_u = false, bool neg_v = false) {
        adj[u << 1 | neg_u].push_back(v << 1 | neg_v);
        radj[v << 1 | neg_v].push_back(u << 1 | neg_u);
    }

    pair<bool, vector<bool>> solve() {
        comp.assign(2 * n, -1);
        visited.assign(2 * n, false);

        for(int i = 0; i < 2 * n; i++) {
            if(!visited[i]) {
                dfs1(i);
            }
        }

        reverse(top_sort.begin(), top_sort.end());
        for(int u: top_sort) {
            if(comp[u] == -1) {
                comp[u] = (int)comp_ids.size();
                comp_ids.push_back(comp[u]);
                dfs2(u);
            }
        }

        vector<bool> assignment(n);
        for(int i = 0; i < n; i++) {
            if(comp[i << 1] == comp[i << 1 | 1]) {
                return {false, {}};
            }

            assignment[i] = comp[i << 1] > comp[i << 1 | 1];
        }

        return {true, assignment};
    }
};

int n, m;
vector<vector<int>> tbl;

void read() {
    cin >> n >> m;
    tbl.assign(n - 1, vector<int>(m - 1));
    for(int i = 0; i < n - 1; i++) {
        string s;
        cin >> s;
        for(int j = 0; j < m - 1; j++) {
            tbl[i][j] = s[j] - '0';
        }
    }
}

void solve() {
    // Once we fix the whole first row and first column of the key A, every
    // remaining cell is forced: A[i][j] = B[i-1][j-1] - A[i-1][j] - A[i][j-1] -
    // A[i-1][j-1]. Writing A[i][0] and A[0][j] as unknown bits, the parity
    // structure makes each forced cell a linear expression in just A[0][0], one
    // row bit (row i) and one column bit (col j), with sign depending on the
    // parities of i and j. The validity constraint A[i][j] in {0, 1} becomes,
    // for each (i, j), a forbidden combination of (row bit, col bit), i.e. a
    // 2-SAT clause over n + m - 2 variables (the n - 1 row bits and m - 1 column
    // bits).
    //
    // We brute force the two choices of A[0][0]; for each we build the 2-SAT
    // instance, where any (value_row, value_col) pair that would push a cell
    // outside {0, 1} is forbidden via the implications "row bit = value_row ->
    // col bit != value_col" and its contrapositive. If the 2-SAT is satisfiable
    // we read off the first row/column from the assignment, fill the rest, and
    // print the key; otherwise the fingerprint is CORRUPT.

    for(int value00 = 0; value00 < 2; value00++) {
        vector<vector<int>> delta(n, vector<int>(m, 0));
        delta[0][0] = value00;

        TwoSat ts(n + m - 2);
        for(int i = 1; i < n; i++) {
            for(int j = 1; j < m; j++) {
                delta[i][j] = tbl[i - 1][j - 1] - delta[i - 1][j] -
                              delta[i][j - 1] - delta[i - 1][j - 1];

                for(int value_row = 0; value_row < 2; value_row++) {
                    for(int value_col = 0; value_col < 2; value_col++) {
                        int real_delta = delta[i][j];
                        if(j % 2 == 0) {
                            real_delta += value_row;
                        } else {
                            real_delta -= value_row;
                        }
                        if(i % 2 == 0) {
                            real_delta += value_col;
                        } else {
                            real_delta -= value_col;
                        }

                        if(real_delta == 0 || real_delta == 1) {
                            continue;
                        }

                        int u = i - 1;
                        int v = j + n - 2;
                        ts.add_implication(
                            u, v, value_row == 0, value_col == 1
                        );

                        ts.add_implication(
                            v, u, value_col == 0, value_row == 1
                        );
                    }
                }
            }
        }

        auto [is_possible, assignment] = ts.solve();
        if(!is_possible) {
            continue;
        }

        vector<vector<int>> ans(n, vector<int>(m, 0));
        ans[0][0] = value00;
        for(int i = 1; i < n; i++) {
            ans[i][0] = assignment[i - 1];
        }

        for(int j = 1; j < m; j++) {
            ans[0][j] = assignment[n + j - 2];
        }

        for(int i = 1; i < n; i++) {
            for(int j = 1; j < m; j++) {
                ans[i][j] = tbl[i - 1][j - 1] - ans[i - 1][j] - ans[i][j - 1] -
                            ans[i - 1][j - 1];
                assert(ans[i][j] == 0 || ans[i][j] == 1);
            }
        }

        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                cout << ans[i][j];
            }
            cout << '\n';
        }

        return;
    }

    cout << "CORRUPT\n";
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int T = 1;
    // cin >> T;
    for(int test = 1; test <= T; test++) {
        read();
        // cout << "Case #" << test << ": ";
        solve();
    }

    return 0;
}
```

4. Python Solution with Comments  
```python
import sys
sys.setrecursionlimit(10**7)

def read():
    H,W = map(int, sys.stdin.readline().split())
    B = [list(map(int, list(sys.stdin.readline().strip())))
         for _ in range(H-1)]
    return H,W,B

# A simple 2-SAT using Kosaraju
class TwoSat:
    def __init__(self,n):
        self.n = n
        self.adj = [[] for _ in range(2*n)]
        self.radj = [[] for _ in range(2*n)]
    def add_imp(self, x, f, y, g):
        # (x is f) => (y is g)
        u = 2*x + (0 if f else 1)
        v = 2*y + (0 if g else 1)
        self.adj[u].append(v)
        self.radj[v].append(u)
    def add_or(self, x, f, y, g):
        # (x=f) or (y=g)
        # ≡ (¬(x=f) => y=g) and (¬(y=g) => x=f)
        self.add_imp(x, not f, y, g)
        self.add_imp(y, not g, x, f)
    def solve(self):
        n2 = 2*self.n
        used = [False]*n2
        order=[]
        def dfs1(u):
            used[u]=True
            for v in self.adj[u]:
                if not used[v]: dfs1(v)
            order.append(u)
        for i in range(n2):
            if not used[i]: dfs1(i)
        comp=[-1]*n2
        cid=0
        def dfs2(u):
            comp[u]=cid
            for v in self.radj[u]:
                if comp[v]<0: dfs2(v)
        for u in reversed(order):
            if comp[u]<0:
                dfs2(u)
                cid+=1
        assign=[False]*self.n
        for i in range(self.n):
            if comp[2*i]==comp[2*i+1]:
                return None
            assign[i] = (comp[2*i] < comp[2*i+1])
        return assign

def solve():
    H,W,B = read()
    # Try A[0][0] = 0 or 1
    for start in (0,1):
        # build delta table by recurrence
        D = [[0]*W for _ in range(H)]
        D[0][0] = start
        for i in range(1,H):
            for j in range(1,W):
                D[i][j] = B[i-1][j-1] - D[i-1][j] - D[i][j-1] - D[i-1][j-1]

        vars = (H-1)+(W-1)
        ts = TwoSat(vars)

        # impose that for each cell A[i][j] computed must be 0 or 1
        for i in range(1,H):
            for j in range(1,W):
                for ci in (0,1):
                    for rj in (0,1):
                        val = D[i][j]
                        # row var index = H-1 + (j-1)
                        # col var index = i-1
                        val += (ci if j%2==0 else -ci)
                        val += (rj if i%2==0 else -rj)
                        if val not in (0,1):
                            idx_c = i-1
                            idx_r = (H-1)+(j-1)
                            # forbid (c[i]=ci AND r[j]=rj)
                            ts.add_or(idx_c, ci^1, idx_r, rj^1)
        res = ts.solve()
        if res is None:
            continue
        # reconstruct A
        A = [[0]*W for _ in range(H)]
        A[0][0] = start
        for i in range(1,H):
            A[i][0] = res[i-1]
        for j in range(1,W):
            A[0][j] = res[(H-1)+(j-1)]
        for i in range(1,H):
            for j in range(1,W):
                A[i][j] = B[i-1][j-1] - A[i-1][j] - A[i][j-1] - A[i-1][j-1]
        # output
        for row in A:
            print("".join(map(str,row)))
        return
    print("CORRUPT")

if __name__=="__main__":
    solve()
```

5. Compressed Editorial  
Treat the top row and left column as Boolean variables (plus two choices for A[0][0]). All other A[i][j] are determined by unwinding the 2×2‐sum equations into a recurrence (δ‐array) plus linear corrections from the row/column variables with signs depending on parity. Enforcing each A[i][j]∈{0,1} forbids certain assignments of a pair (row_var, col_var), which is exactly a 2‐SAT clause. Build the implication graph in O(HW), solve 2‐SAT, and reconstruct or report CORRUPT.