#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <vector>
#include <algorithm>
#include "testlib.h"

using namespace std;

#define VI vector<int>

#define FOR(i,n) for (int i = 0; i < (int)(n); i++)

#define PB push_back
#define SZ(a) a.size()
#define MP make_pair
#define PII pair<int, int>
#define VI vector<int>
#define VVI vector<VI >
#define PII pair<int, int>

int n, res;

#define FORE(i, a, b) for (int i = (int)(a); i <= (int)(b); i++)
const int INF = 1000000000;

char a[512][513];

int dp_r[512][512][10];
char pr_r[512][512][10];

//int dp_b[512][512][10];
//int dp_w[512][512][10];

int bc[515][515], wc[515][515];

//01
//23

int query_bl(int x1, int y1, int x2, int y2)
{
	x2++; y2++;
	return bc[x2][y2] - bc[x2][y1] - bc[x1][y2] + bc[x1][y1];
}

int query_wt(int x1, int y1, int x2, int y2)
{
	x2++; y2++;
	return wc[x2][y2] - wc[x2][y1] - wc[x1][y2] + wc[x1][y1];
}

int calc_bl(int x0, int y0, int p2)
{
	int n = 1<<p2;
	return query_wt(x0, y0, x0 + n - 1, y0 + n - 1);
}

int calc_wt(int x0, int y0, int p2)
{
	int n = 1<<p2;
	return query_bl(x0, y0, x0 + n - 1, y0 + n - 1);
}

void coord(int x, int y, int n, int k, int &xx, int &yy)
{
	xx = x;
	yy = y;
	if (k == 1) yy += n;
	if (k == 2) xx += n;
	if (k == 3) yy += n;
	if (k == 3) xx += n;
}

int calc_r(int x0, int y0, int p2)
{
	int &res = dp_r[x0][y0][p2];

	if (!p2) return 0;

	if (!res)
	{
		res = INF;

		int N = 1<<p2;
		int n = N / 2;

		FOR(wt, 4) FOR(bl, 4) if (wt != bl)
		{
			int t = 0;

			int xx, yy, x = x0, y = y0;

			coord(x, y, n, wt, xx, yy);
			t += calc_wt(xx, yy, p2-1);

			coord(x, y, n, bl, xx, yy);
			t += calc_bl(xx, yy, p2-1);

			FOR(tt, 4) if (tt != wt && tt != bl)
			{
				coord(x, y, n, tt, xx, yy);
				t += calc_r(xx, yy, p2-1);
			}

			if (t < res)
			{
				res = t;
				pr_r[x0][y0][p2] = wt + (bl<<2);
			}
		}

		res++;
	}

	return res - 1;
}

void print_bl(int x, int y, int d)
{
	FORE(i, x, x + d - 1) FORE(j, y, y + d - 1)
		a[i][j] = '1';
}

void print_wt(int x, int y, int d)
{
	FORE(i, x, x + d - 1) FORE(j, y, y + d - 1)
		a[i][j] = '0';
}

void print(int x, int y, int p2)
{
	if (!p2)
	{
		return;
	}
	int v = pr_r[x][y][p2];
	int wt = v & 3;
	int bl = v >> 2;
	int xx, yy;
	int N = 1<<p2;
	FOR(k, 4) if (k != wt && k != bl)
	{
		coord(x, y, N/2, k, xx, yy);
		print(xx, yy, p2-1);
	}
	coord(x, y, N/2, bl, xx, yy);
	print_bl(xx, yy, N / 2);
	coord(x, y, N/2, wt, xx, yy);
	print_wt(xx, yy, N / 2);
}

int solve()
{
	FOR(i, n) FOR(j, n)
		bc[i+1][j+1] = (a[i][j] == '1') + bc[i+1][j] + bc[i][j+1] - bc[i][j],
		wc[i+1][j+1] = (a[i][j] == '0') + wc[i+1][j] + wc[i][j+1] - wc[i][j];

	int p2 = 0;
	while ((1<<p2) != n) p2++;

	return calc_r(0, 0, p2);
}

int main(int argc, char *argv[])
{
	registerTestlibCmd(argc, argv);

	n = inf.readInt();

	int res_j;
	sscanf(ans.readWord().c_str(), "%d", &res_j);
	sscanf(ouf.readWord().c_str(), "%d", &res);
	if (res != res_j)
		quitf(_wa, "Wrong answer: got %d, expected %d", res, res_j);
	int diff_c = 0;
	//cout<<res<<endl;
	FOR(i,n)
	{
		string t = ouf.readWord();
		string ja = inf.readWord();
		//cout<<t<<endl;
		//cout<<ja<<endl;
		if (t.length() != n)
			quitf(_wa, "Wrong line length: got %d, expected %d", t.length(), n);
		for (int j = 0; j < n; j++)
		{
			a[i][j] = t[j];
			if (t[j] != '0' && t[j] != '1')
				quitf(_wa, "Wrong character in output <%c>", t[j]);
			diff_c += t[j] != ja[j];
		}
	}
	if (diff_c != res)
		quitf(_wa, "Wrong output picture difference. Declared %d, actual %d", res, diff_c);
	if (solve() != 0)
		quitf(_wa, "Wrong output picture");
	quitf(_ok, "OK %d", n);
}
