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 <iostream>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <fstream>
#include <cassert>
#include <cstring>
#include <unordered_set>
#include <unordered_map>
#include <numeric>
#include <ctime>
#include <bitset>
#include <complex>
#include <random>
#include <functional>

using namespace std;


#define int long long 

const int LIM = 2e6 + 7;
const int N = 500;

int pr[LIM];
vector<int> primes;

int lcm(int a, int b) {
    #ifdef LOCAL
    return a / (gcd(a, b)) * b;
    #else
    return a / (__gcd(a, b)) * b;
    #endif
}

void init() {
    fill(pr, pr + LIM, 1);
    for (int i = 2; i < LIM; i++) {
        if (pr[i]) {
            primes.push_back(i);
            for (int j = 2 * i; j < LIM; j += i) {
                pr[j] = 0;
            }
        }
    }
}

int ans[N][N];

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    init();
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            ans[i][j] = 1;
        }
    }
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if ((i + j) & 1) {
                ans[i][j] *= primes[(i + j) / 2];
            }
        }
    }
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if ((i - j) % 2 != 0) {
                ans[i][j] *= primes[(i - j) + 2 * N];
            }
        }
    }
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if ((i + j) % 2 == 0) {
                if (i > 0) {
                    ans[i][j] = lcm(ans[i][j], ans[i - 1][j]);
                }
                if (j > 0) {
                    ans[i][j] = lcm(ans[i][j], ans[i][j - 1]);
                }
                if (i + 1 < N) {
                    ans[i][j] = lcm(ans[i][j], ans[i + 1][j]);
                }
                if (j + 1 < N) {
                    ans[i][j] = lcm(ans[i][j], ans[i][j + 1]);
                }
                ans[i][j]++;
                // cerr << ans[i][j] << '\n';
            }
        }
    }
    {
        set<int> s;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                s.insert(ans[i][j]);
            }
        }
        assert(s.size() == N * N);
        // cerr << *s.rbegin() << endl;
        assert(*s.rbegin() <= 1e15);
    }
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cout << ans[i][j] << ' ';
        }
        cout << '\n';
    }
}