#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
using i128 = __int128_t;
static const int THRESH = 64; // порог для обычного умножения
// печать i64
inline void print_i64(i64 x) { cout << x; }
// обычное умножение n×n (с безопасной суммой)
vector<vector<i64>> mul_naive(const vector<vector<i64>>& A,
const vector<vector<i64>>& B) {
int n = (int)A.size();
vector<vector<i64>> C(n, vector<i64>(n, 0));
for (int i = 0; i < n; ++i) {
for (int k = 0; k < n; ++k) {
i64 aik = A[i][k];
for (int j = 0; j < n; ++j) {
// аккумулируем в 128 битах и приводим назад к i64
i128 cur = (i128)aik * (i128)B[k][j] + (i128)C[i][j];
C[i][j] = (i64)cur;
}
}
}
return C;
}
vector<vector<i64>> add(const vector<vector<i64>>& A,
const vector<vector<i64>>& B) {
int n = (int)A.size();
vector<vector<i64>> C(n, vector<i64>(n));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
C[i][j] = A[i][j] + B[i][j];
return C;
}
vector<vector<i64>> sub(const vector<vector<i64>>& A,
const vector<vector<i64>>& B) {
int n = (int)A.size();
vector<vector<i64>> C(n, vector<i64>(n));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
C[i][j] = A[i][j] - B[i][j];
return C;
}
vector<vector<i64>> strassen(const vector<vector<i64>>& A,
const vector<vector<i64>>& B) {
int n = (int)A.size();
if (n <= THRESH) return mul_naive(A, B);
int h = n / 2;
// разбиение на кварталы
vector<vector<i64>> A11(h, vector<i64>(h)), A12(h, vector<i64>(h)),
A21(h, vector<i64>(h)), A22(h, vector<i64>(h));
vector<vector<i64>> B11(h, vector<i64>(h)), B12(h, vector<i64>(h)),
B21(h, vector<i64>(h)), B22(h, vector<i64>(h));
for (int i = 0; i < h; ++i) {
for (int j = 0; j < h; ++j) {
A11[i][j] = A[i][j];
A12[i][j] = A[i][j + h];
A21[i][j] = A[i + h][j];
A22[i][j] = A[i + h][j + h];
B11[i][j] = B[i][j];
B12[i][j] = B[i][j + h];
B21[i][j] = B[i + h][j];
B22[i][j] = B[i + h][j + h];
}
}
// Классическая нумерация M1..M7
auto M1 = strassen(add(A11, A22), add(B11, B22));
auto M2 = strassen(add(A21, A22), B11);
auto M3 = strassen(A11, sub(B12, B22));
auto M4 = strassen(A22, sub(B21, B11));
auto M5 = strassen(add(A11, A12), B22);
auto M6 = strassen(sub(A21, A11), add(B11, B12));
auto M7 = strassen(sub(A12, A22), add(B21, B22));
// Сборка блоков результата
auto C11 = sub(add(M1, M4), add(M5, vector<vector<i64>>(h, vector<i64>(h, 0))));
for (int i = 0; i < h; ++i) // C11 = M1 + M4 - M5 + M7
for (int j = 0; j < h; ++j)
C11[i][j] += M7[i][j];
auto C12 = add(M3, M5); // C12 = M3 + M5
auto C21 = add(M2, M4); // C21 = M2 + M4
auto C22 = add(sub(M1, M2), add(M3, M6)); // C22 = M1 - M2 + M3 + M6
// склейка
vector<vector<i64>> C(n, vector<i64>(n));
for (int i = 0; i < h; ++i) {
for (int j = 0; j < h; ++j) {
C[i][j] = C11[i][j];
C[i][j + h] = C12[i][j];
C[i + h][j] = C21[i][j];
C[i + h][j + h] = C22[i][j];
}
}
return C;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
if (!(cin >> n)) return 0;
vector<vector<i64>> A(n, vector<i64>(n));
vector<vector<i64>> B(n, vector<i64>(n));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
cin >> A[i][j];
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
cin >> B[i][j];
auto C = strassen(A, B);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (j) cout << ' ';
print_i64(C[i][j]);
}
cout << '\n';
}
return 0;
}