#include #include #include #include using namespace __gnu_pbds; using namespace std; using namespace atcoder; using mint = modint998244353; #define rep(i, n) for (int i = 0; i < (int)(n); i++) #define rep1(i, n) for (int i = 1; i < (int)(n); i++) #define rrep(i, n) for (int i = (int)(n) - 1; i >= 0; i--) #define rrep1(i, n) for (int i = (int)(n) - 1; i >= 1; i--) #define ll long long #define double long double #define ull unsigned long long #define sll __int128_t #define sull __uint128_t #define ALL(v) (v).begin(), (v).end() #define NP next_permutation #define PLL pair #define VL vector #define VVL vector> #define VVVL vector>> #define VPLL vector> #define STL set #define MPLL map #define SP fixed << setprecision(12) #define hashmap unordered_set #define popcount __builtin_popcountll constexpr ll inf = 4001001001001001001ll; constexpr ll mod = 998244353; constexpr double pi = 3.141592653589793; constexpr double eps = 0.00000000001; vector d8x = {1, 1, 0, -1, -1, -1, 0, 1}; vector d8y = {0, 1, 1, 1, 0, -1, -1, -1}; vector d4x = {1, 0, -1, 0}; vector d4y = {0, 1, 0, -1}; // 小数出力 // cout << setprecision(12); // struct typedef tree< int, null_type, less, rb_tree_tag, tree_order_statistics_node_update> ordered_set; struct Ruiseki { vector v; Ruiseki(vector& vec) { ll n = vec.size(); v.resize(n + 1); rep(i, n) v[i + 1] = v[i] + vec[i]; } ll get(ll l, ll r) { // 開区間になりました return v[r] - v[l]; } }; // max template inline bool chmax(T1& a, T2 b) { return a < b && (a = b, true); } // min template inline bool chmin(T1& a, T2 b) { return a > b && (a = b, true); } // join template string join(vector& vec, const string& sp = " ") { int si = vec.size(); if (si == 0) { return ""; } else { stringstream ss; rep(i, si - 1) { ss << vec[i] << sp; } ss << vec[si - 1]; return ss.str(); } } // print template void pr_single(const T& x) { if constexpr (requires { x.val(); }) cout << x.val(); else if constexpr (requires { typename T::value_type; } && !requires { x.substr(0); }) { using elem_type = typename T::value_type; constexpr bool is_container_of_container = requires { typename elem_type::value_type; } && !requires(elem_type e) { e.substr(0); }; for (int i = 0; i < (int)x.size(); i++) { pr_single(x[i]); if (i != (int)x.size() - 1) { if constexpr (is_container_of_container) { cout << "\n"; } else { cout << " "; } } } } else if constexpr (requires { x.first; x.second; }) { pr_single(x.first); cout << " "; pr_single(x.second); } else if constexpr (is_same_v || is_same_v) { using unsigned_type = __uint128_t; unsigned_type value; bool negative = false; if constexpr (is_same_v) { negative = x < 0; value = negative ? static_cast(-(x + 1)) + 1 : static_cast(x); } else { value = x; } string digits; do { digits.push_back('0' + static_cast(value % 10)); value /= 10; } while (value > 0); if (negative) digits.push_back('-'); reverse(ALL(digits)); cout << digits; } else if constexpr (requires { cout << x; }) { cout << x; } } void pr() { cout << endl; } template void pr(const Head& head, const Tail&... tail) { pr_single(head); if constexpr (sizeof...(tail) > 0) { cout << " "; pr(tail...); } else cout << endl; } // Yes string Yes(bool x) { if (x) return "Yes\n"; return "No\n"; } string YES(bool x) { if (x) return "YES\n"; return "NO\n"; } ll Digit(ll n) { ll ans = 0; while (n > 0) { n /= 10; ans++; } return ans; } bool in_range(int l, int x, int r) { // 閉区間 return ((l <= x) && (x <= r)) || ((r <= x) && (x <= l)); } int div_ceil(int x, int y) { return (x + y - 1) / y; } void yakubun(ll& a, ll& b) { if (a < 0) { a = -a; b = -b; } if (a == 0) { b = 1; return; } if (b == 0) { a = 1; return; } ll g = gcd(abs(a), abs(b)); a /= g; b /= g; // pr(a, b); } void swap(pair& p) { auto [a, b] = p; p = {b, a}; } ll _sqrt(ll x) { ll a = sqrt(x); while ((a + 1) * (a + 1) <= x) a++; while (a * a > x) a--; return a; } ll _pow(ll x, ll n) { ll res = 1; while (n > 0) { if (n & 1) res *= x; x *= x; n >>= 1; } return res; } ll bs(ll l, ll r, function f) { // l-> false, r->true while (r - l > 1) { ll mid = l + (r - l) / 2; if (f(mid)) r = mid; else l = mid; } return r; } void solve() { } struct GetKth { multiset lower; multiset upper; ll k; GetKth(ll a) { k = a; } void insert(string n) { lower.insert(n); if ((ll)lower.size() > k) { string a = *lower.rbegin(); lower.erase(lower.find(a)); upper.insert(a); } } string get() { if ((ll)lower.size() < k) return "xxxxxxx"; else return *lower.rbegin(); } void erase(string n) { if (n <= get()) { // print("erase",n); lower.erase(lower.find(n)); if ((ll)upper.size() > 0) { string a = *upper.begin(); // print("move",a); upper.erase(upper.find(a)); lower.insert(a); } } else { upper.erase(upper.find(n)); } } ll size() { return upper.size() + lower.size(); } }; vector> solve(vector v) { ll n = v.size(); vector> ans(21); rep(bit, 1 << n) { ll val = 0; ll cnt = 0; rep(i, n) { if (!((bit >> i) & 1)) continue; val += v[i]; cnt++; } ans[cnt].push_back(val); } rep(i, 21) sort(ALL(ans[i])); return ans; } sll op(sll a, sll b) { return a + b; } sll e() { return 0; } struct UnionFind { vector data; // 負ならサイズ 正なら親ノード UnionFind(int sz) { data.assign(sz, -1); } bool unite(int x, int y) { x = find(x), y = find(y); if (x == y) return (false); if (data[x] > data[y]) swap(x, y); // Xの方が大きい状態にする data[x] += data[y]; data[y] = x; return (true); } int find(int k) { if (data[k] < 0) return (k); return (data[k] = find(data[k])); } int size(int k) { return (-data[find(k)]); } bool same(int x, int y) { return find(x) == find(y); } }; ll solve(ll n, ll offset) { ll cnt = 0; rep(i, n) { ll s = i + offset; rep(j, i + 1) { cnt += 2; cnt += 1; s++; } } return cnt; } void output(ll n, ll offset) { rep(i, n) { ll s = i + offset; rep(j, i + 1) { if (s % 3 == 0) cout << 2 << ' '; else cout << 1 << ' '; s++; } cout << endl; } } signed main() { ll n; cin >> n; ll a, b, c; a = solve(n, 0); b = solve(n, 1); c = solve(n, 2); if (a <= b && a <= c) output(n, 0); else if (b <= a && b <= c) output(n, 1); else output(n, 2); }