// vvvvvvvvvvvv TEMPLATE vvvvvvvvvvvv
#include <bits/stdc++.h>
using namespace std; using ll = long long; using P = pair<ll, ll>;
const ll linf = 1e18; const double eps = 1e-12, pi = acos(-1);
#define FOR(i,a,b) for (ll i=(a),__last_##i=(b);i<__last_##i;i++)
#define RFOR(i,a,b) for (ll i=(b)-1,__last_##i=(a);i>=__last_##i;i--)
#define REP(i,n) FOR(i,0,n)
#define RREP(i,n) RFOR(i,0,n)
#define __GET_MACRO3(_1, _2, _3, NAME, ...) NAME
#define each(i,a) for (auto&& i : a)
#define rep(...) __GET_MACRO3(__VA_ARGS__, FOR, REP)(__VA_ARGS__)
#define rrep(...) __GET_MACRO3(__VA_ARGS__, RFOR, RREP)(__VA_ARGS__)
#define pb push_back
#define eb emplace_back
#define all(a) begin(a),end(a)
#define chmin(x,v) x = min(x, v)
#define chmax(x,v) x = max(x, v)
template<typename T> ll min(ll a, const T&& b) { return a < b ? a : b; }
template<typename T> ll min(const T&& a, ll b) { return a < b ? a : b; }
template<typename T> ll max(ll a, const T&& b) { return a > b ? a : b; }
template<typename T> ll max(const T&& a, ll b) { return a > b ? a : b; }
template<typename Head> void out(Head h) { cout << h << endl; } template<typename Head, typename... Tail>void out(Head h, Tail... t) { cout << h << " "; out(t...); }
template<typename T> istream& operator>>(istream& is, vector<T>& v) { each(x,v) is >> x; return is; }
template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) { rep(i,v.size()) { if (i) os << " "; os << v[i]; } return os; }
ostream& operator<<(ostream& os, const vector<string>& v) { rep(i,v.size()) { if (i) os << endl; os << v[i]; } return os; }
template<typename T> ostream& operator<<(ostream& os, const vector<vector<T>>& v) { rep(i,v.size()) { if (i) os << endl; os << v[i]; } return os; }
template<typename T1, typename T2> ostream& operator<<(ostream& os, const pair<T1, T2>& p) { return os << "(" << p.first << ", " << p.second << ")"; }
struct yes_no : std::numpunct<char> { string_type do_truename() const { return "Yes"; } string_type do_falsename() const { return "No"; } };
void solve(); int main() {
  ios::sync_with_stdio(false); cin.tie(0); locale loc(locale(), new yes_no); cout.imbue(loc); cout << fixed << setprecision(10) << boolalpha;
  solve();
}
// ^^^^^^^^^^^^ TEMPLATE ^^^^^^^^^^^^

bool is_prime(ll n) {
  if (n <= 1) return false;
  if (n == 2) return true;
  for (ll i = 2; i * i <= n; ++i) {
    if (n % i == 0) return false;
  }
  return true;
}

random_device rnd;

void shuffle(vector<ll>& v) {
  const ll n = v.size();
  rep(i, n) {
    swap(v[i], v[rnd() % n]);
  }
}

vector<vector<ll>> solve(ll n, const vector<ll>& primes) {
  ll pos = 0;
  vector<vector<ll>> res(n, vector<ll>(n, 0.));
  rep(i, n) rep(j, i) {
    res[i][j] = res[j][i] = primes[pos++];
  }
  ll mx = ll(8e10);
  double coe = linf;
  rep(i, n) rep(j, i) {
    chmin(coe, mx / log(res[i][j]));
  }
  rep(i, n) rep(j, i) {
    res[i][j] = res[j][i] = ll(log(res[i][j]) * coe);
  }
  return res;
}

bool judge(const vector<vector<ll>>& ans) {
  // vector<ll> ord
  return true;
}

bool output(const vector<vector<ll>>& ans) {
  cout << ans << endl;
}

void solve() {
  ll n; cin >> n;
  vector<ll> primes;
  primes.pb(2);
  rep(i, 300) {
    ll x;
    for (x = primes.back()+1; !is_prime(x); ++x);
    primes.pb(x);
  }
  while (true) {
    shuffle(primes);
    auto ans = solve(n, primes);
    if (judge(ans)) {
      output(ans);
      return;
    }
  }
}
