// #define DEBUGGING
#include <bits/stdc++.h>
#define endl '\n'
#define ALL(V) (V).begin(), (V).end()
#define ALLR(V) (V).rbegin(), (V).rend()
using ll = std::int64_t;
using ull = std::uint64_t;
using PLL = std::pair<ll, ll>;
using TLL = std::tuple<ll, ll, ll>;
template <typename T> using V = std::vector<T>;
template <typename T> using VV = V<V<T>>;
template <typename T> const T& var_min(const T &t) { return t; }
template <typename T> const T& var_max(const T &t) { return t; }
template <typename T, typename... Tail> const T& var_min(const T &t, const Tail&... tail) { return std::min(t, var_min(tail...)); }
template <typename T, typename... Tail> const T& var_max(const T &t, const Tail&... tail) { return std::max(t, var_max(tail...)); }
template <typename T, typename... Tail> void chmin(T &t, const Tail&... tail) { t = var_min(t, tail...); }
template <typename T, typename... Tail> void chmax(T &t, const Tail&... tail) { t = var_max(t, tail...); }
template <typename T> const T& clamp(const T &t, const T &low, const T &high) { return std::max(low, std::min(high, t)); }
template <typename T> void chclamp(T &t, const T &low, const T &high) { return t = clamp(t, low, high); }
namespace init__ { struct InitIO { InitIO() { std::cin.tie(nullptr); std::ios_base::sync_with_stdio(false); std::cout << std::fixed << std::setprecision(30); } } init_io; }
#define mv_rec make_v(init, tail...)
template <typename T> T make_v(T init) { return init; }
template <typename T, typename... Tail> auto make_v(T init, size_t s, Tail... tail) { return V<decltype(mv_rec)>(s, mv_rec); }
#undef mv_rec
using namespace std;

#ifdef DEBUGGING
#include "../../debug/debug.cpp"
#else
#define DEBUG(...) 0
#define DEBUG_SEPARATOR_LINE 0
#endif
    
const int K = 38;
const int N = (K - 1) * (K - 1) + K;
int grid[N][K];
using BS = bitset<N>;

void output(int i) {
    for(int j = 0; j < K; j++) cout << grid[i][j] << " \n"[j + 1 == K];
}

void check() {
    V<BS> bsv(N);
    for(int i = 0; i < N; i++) {
        for(int j = 0; j < K; j++) {
            int n = grid[i][j] - 1;
            bsv[i].set(n, 1);
        }
    }
    for(int i = 0; i < N; i++) for(int j = i + 1; j < N; j++) {
        if((bsv[i] & bsv[j]).count() != 1) {
            cout << (bsv[i] & bsv[j]).count() << endl;
            for(int k = 0; k < N; k++) if(bsv[i][k] && bsv[j][k]) cout << k + 1 << ", ";
            cout << endl;
            cout << i << " : ";
            output(i);
            cout << j << " : ";
            output(j);
            assert(false);
        }
    }
}

int main() {
    int num = 1;
    for(int i = 0; i < K - 1; i++) {
        for(int j = 0; j < K - 1; j++) grid[i * (K - 1) + K + j][0] = num;
        num++;
    }
    map<int, V<int>> mp;
    for(int i = 1; i < K; i++) {
        for(int j = 0; j < K - 1; j++) {
            int offset = j;
            for(int k = 0; k < K - 1; k++) {
                grid[k * (K - 1) + K + offset][i] = num;
                mp[num].push_back(k * (K - 1) + K + offset);
                offset += (i - 1);
                offset %= (K - 1);
            }
            num++;
        }
    }
    
    {
        for(int i = 0; i < K; i++) grid[i][0] = N;
        set<int> num;
        for(int i = 1; i < N; i++) num.insert(i);
        for(int i = 0; i < K; i++) {
            bool used[N] = {};
            int j = 1;
            auto cpy = num;
            for(auto e : cpy) {
                bool ok = true;
                for(int u : mp[e]) if(used[u]) {
                    ok = false;
                    break;
                }
                if(ok) {
                    grid[i][j++] = e;
                    num.erase(e);
                    for(int u : mp[e]) used[u] = true;
                }
                if(j == K) break;
            }
        }
    }

    check();
    cout << N << ' ' << K << endl;
    for(int i = 0; i < N; i++) output(i);
    return 0;
}


Measured memory_bytes: 1292