Problem:
Score : 1100 points

Problem Statement

You are given an integer N.

Construct any one N-by-N matrix a that satisfies the conditions below. It can be proved that a solution always exists under the constraints of this problem.

1 \leq a_{i,j} \leq 10^{15}

a_{i,j} are pairwise distinct integers.

There exists a positive integer m such that the following holds: Let x and y be two elements of the matrix that are vertically or horizontally adjacent. Then, {\rm max}(x,y) {\rm mod} {\rm min}(x,y) is always m.

Constraints

2 \leq N \leq 500

Input

Input is given from Standard Input in the following format:

N

Output

Print your solution in the following format:

a_{1,1} ... a_{1,N}
:
a_{N,1} ... a_{N,N}

Sample Input 1

2

Sample Output 1

4 7
23 10

For any two elements x and y that are vertically or horizontally adjacent, {\rm max}(x,y) {\rm mod} {\rm min}(x,y) is always 3.

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
using namespace std;
typedef long double ld;
typedef long long ll;
const int maxN = 505;
ll a[maxN][maxN];
vector < int > primes;
int n;
bool used[maxN * maxN * 10];
ll gcd(ll a, ll b) {
    while (a > 0 && b > 0) {
        if (a < b) swap(a, b);
        a %= b;
    }
    return a + b;
}
ll lcm(ll a, ll b) {
    return (a * (b / gcd(a, b)));
}
int main() {
    ios_base::sync_with_stdio(false);
    //freopen("input.txt", "r", stdin);
    cin >> n;
    int max_n = 500;
    for (int i = 2; ; i++) {
        if (used[i]) continue;
        primes.push_back(i);
        if (primes.size() > 2 * max_n + 10) {
            break;
        }
        for (int j = i; j < maxN * maxN * 10; j += i) used[j] = true;
    }
    set < ll > all;
    for (int i = 1; i <= max_n; i++) {
        for (int j = 1; j <= max_n; j++) {
            if (((i + j) % 2) == 0) {
                a[i][j] = 1LL * primes[(i + j) / 2] * primes[(i - j) / 2 + max_n + 2 + (max_n / 2)];
                all.insert(a[i][j]);
            }
        }
    }
    ll mx = 1;
    for (int i = 1; i <= max_n; i++) {
        for (int j = 1; j <= max_n; j++) {
            if (((i + j) % 2) == 0) continue;
            a[i][j] = 1;
            if (i > 1) a[i][j] = lcm(a[i][j], a[i - 1][j]);
            if (i < max_n) a[i][j] = lcm(a[i + 1][j], a[i][j]);
            if (j < max_n) a[i][j] = lcm(a[i][j], a[i][j + 1]);
            if (j > 1) a[i][j] = lcm(a[i][j], a[i][j - 1]);
            a[i][j]++;
            mx = max(mx, a[i][j]);
            all.insert(a[i][j]);
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cout << a[i][j] << " ";
        }
        cout << '\n';
    }
    return 0;
}