#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <set>

#define FILL(a, n, x) memset((a), (x), sizeof ((a)[0]) * (n))
#define COPY(a, n, b) memcpy((b), (a), sizeof ((a)[0]) * (n))
#define FILLA(a, x) memset((a), (x), sizeof (a))
#define COPYA(a, b) memcpy((b), (a), sizeof (a))

using namespace std;

typedef long long li;
typedef unsigned long long lu;
const li infl = ~0LLU >> 2;

template <class T>
inline void Min(T &x, T y) {
  if (y < x) x = y;
}
template <class T>
inline void Max(T &x, T y) {
  if (y > x) x = y;
}

const int mod = 1e9 + 7;
inline int Add(int x) { return x >= mod ? x - mod : x; }
inline void Add(int &x, int y) { x += y; if (x >= mod) x -= mod; }
inline int Sub(int x) { return x < 0 ? x + mod : x; }
inline void Sub(int &x, int y) { x -= y; if (x < 0) x += mod; }
inline int Mul(int x, int y) { return (int)((li)x * y % mod); }
inline int Mul(int x, int y, int z) { return Mul(x, Mul(y, z)); }
int Pow(int x, int y) {
  int z = 1;
  for (; y; y >>= 1) {
    if (y & 1) z = Mul(z, x);
    x = Mul(x, x);
  }
  return z;
}
int Inv(int x) {
  return Pow(x, mod - 2);
}

// ----------------------------------------

const int maxn = 500;
const int maxp = 50000;

int n;
int prime[maxp], cntp;
bool is[maxp + 1];

li a[maxn][maxn], b[maxn][maxn];
li ans[maxn][maxn];

int main(void) {
  scanf("%d", &n);
  FILLA(is, 1);
  cntp = 0;
  for (int i = 2; i <= maxp; ++i) {
    if (is[i]) {
      prime[cntp++] = i;
      for (int j = 2 * i; j <= maxp; j += i) {
        is[j] = false;
      }
    }
  }

  int next = 1;
  a[0][0] = prime[next++];
  if (n & 1) {
    b[0][n - 1] = prime[next++];
  } else {
    b[0][n - 2] = prime[next++];
    b[1][n - 1] = prime[next++];
  }
  for (int i = 2; i < n; i += 2) {
    a[0][i] = prime[next++];
    a[i][0] = prime[next++];
    if (n & 1) {
      b[0][n - i - 1] = prime[next++];
      b[i][n - 1] = prime[next++];
    } else {
      b[0][n - i - 2] = prime[next++];
      b[i + 1][n - 1] = prime[next++];
    }
  }

  for (int i = 1; i < n; ++i) {
    for (int j = 1; j < n; ++j) {
      if (~(i + j) & 1) {
        a[i][j] = a[i - 1][j - 1];
      }
    }
  }
  for (int i = 1; i < n; ++i) {
    for (int j = n - 2; j >= 0; --j) {
      if (~(i + j) & 1) {
        b[i][j] = b[i - 1][j + 1];
      }
    }
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      if (~(i + j) & 1) {
        ans[i][j] = a[i][j] * b[i][j];
      }
      // printf("a(%d, %d) = %d, b = %d, ans = %lld\n", i, j, (int)a[i][j], (int)
      //        b[i][j], ans[i][j]);
    }
  }

  const int dx[] = {-1, 0, 1, 0};
  const int dy[] = {0, 1, 0, -1};

  set<li> S;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      if ((i + j) & 1) {
        ans[i][j] = 1;
        for (int d = 0; d < 4; ++d) {
          int i2 = i + dx[d];
          int j2 = j + dy[d];
          // printf("(%d, %d)\n", i2, j2);
          if (i2 >= 0 && i2 < n && j2 >= 0 && j2 < n) {
            ans[i][j] = ans[i][j] / __gcd(ans[i][j], ans[i2][j2]) * ans[i2][j2];
          }
        }
      } else {
        S.insert(ans[i][j]);
      }
    }
  }

  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      if ((i + j) & 1) {
        for (int k = 1; ; ++k) {
          li t = ans[i][j] * k + 1;
          if (!S.count(t)) {
            S.insert(t);
            ans[i][j] = t;
            break;
          }
        }
      }
      printf("%lld%c", ans[i][j], " \n"[j == n - 1]);
    }
  }
}




Measured memory_bytes: 20608