#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx")
#pragma GCC optimize("unroll-loops")
//#pragma warning(disable : 4996)

#ifdef _MSC_VER
#include <intrin.h>
#define __builtin_popcount __popcnt
#define __builtin_popcountll __popcnt64
#endif

#include <limits.h>
#include <math.h>
#include <time.h>

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <complex>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

#define REP(i, n) for (int i = 0; i < (n); ++i)
#define REPR(i, n) for (int i = n - 1; i >= 0; --i)
#define FOR(i, m, n) for (int i = m; i < n; ++i)
#define FORR(i, m, n) for (int i = m - 1; i >= n; --i)
#define SORT(v, n) sort(v, v + n);
#define VSORT(v) sort(v.begin(), v.end());
#define REVERSE(v, n) reverse(v, v + n);
#define VREVERSE(v) reverse(v.begin(), v.end())
#define ll long long
#define print(x) cout << (x) << '\n'
#define pe(x) cout << (x) << " "
#define DEBUG(x) cout << #x << ": " << x << endl
#define lb(v, n) lower_bound(v.begin(), v.end(), (n))
#define ub(v, n) upper_bound(v.begin(), v.end(), (n))
//#define int long long
//#define double long double
#define all(x) (x).begin(), (x).end()
#define print_space(v) REP(i, v.size()) cout << v[i] << ((i == v.size() - 1) ? "\n" : " ")
template <typename T1, typename T2> inline void chmin(T1& a, T2 b) {
    if (a > b) a = b;
}
template <typename T1, typename T2> inline void chmax(T1& a, T2 b) {
    if (a < b) a = b;
}
typedef pair<int, int> pii;
typedef pair<long long, long long> pll;
std::random_device rd;
std::mt19937 mt(rd());
constexpr ll MOD = 1e9 + 7;
constexpr int MAX = 10050;
const double pi = acos(-1);
constexpr double EPS = 1e-8;
constexpr ll LINF = 1e18 + 1;
constexpr int INF = 1e9 + 1;
using ull = uint64_t;
unsigned long xor128(void) {
    static unsigned long x = 123456789, y = 362436069, z = 521288629, w = 88675123;
    unsigned long t;
    t = (x ^ (x << 11));
    x = y;
    y = z;
    z = w;
    return (w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)));
}
constexpr int N = 26;
int D;
int C[30];
int S[400][30];

int las[400][N + 1];
int gain = 0, ngain = 0;
// int loss[30];
int loss = 0;
int losses[30][400];
int lss[30];
int ans[400];
set<int> position[N];
int calc_score_init() {
    int ret = 0;
    gain = 0;
    REP(j, N) {
        position[j].insert(-1);
        position[j].insert(D);
        las[0][j] = -1;
        losses[j][0] = 0;
    }
    REP(i, D) {
        int j = ans[i];
        position[j].insert(i);
        ret += S[i][j];
        gain += S[i][j];
        las[i][j] = i;
        REP(k, N) {
            ret -= C[k] * (i - las[i][k]);
            loss += C[k] * (i - las[i][k]);
            losses[k][i + 1] = losses[k][i] + C[k] * (i - las[i][k]);
        }
        REP(k, N) { las[i + 1][k] = las[i][k]; }
    }
    REP(k, N) lss[k] += losses[k][D];
    return ret;
}

int calcmax(vector<int>& ans) {
    int d = ans.size();
    REP(j, N) las[0][j] = -1;
    REP(i, d) {
        int j = ans[i];
        las[i][j] = i;
        REP(k, N) { las[i + 1][k] = las[i][k]; }
    }
    int idx = 0;
    int score = -INF;
    REP(j, N) {
        int res = S[d][j];
        REP(k, N) {
            if (k != j) res -= C[k] * (d - las[d][k]);
        }
        if (res > score) {
            score = res;
            idx = j;
        }
    }
    return idx;
}

void input() {
    cin >> D;
    REP(i, N) cin >> C[i];
    REP(i, D) {
        REP(j, N) { cin >> S[i][j]; }
    }
}

void update_loss(int j) {
    auto itr = position[j].begin();
    int pre = -1;
    lss[j] = 0;
    if (position[j].empty()) return;
    itr++;

    while (itr != position[j].end()) {
        int l = (*itr) - pre - 1;
        lss[j] += C[j] * l * (l + 1) / 2;
        pre = *itr;
        itr++;
    }
}

int ret[400];

void fail(string s) {
    cerr << s << endl;
    exit(1);
}

void solve() {
    // cerr<<"a"<<endl;
    const double LIMIT = 1970;
    int t = 0;
    double start_temp = 1000, end_temp = 10;
    clock_t start = clock();
    int accepted = 0;
    double TIME = 0;
    const double m = (end_temp - start_temp) / LIMIT;
    int pre_val = 0, new_val = 0;
    double temp = start_temp;
    input();

    vector<int> tmp;
    REP(i, D) {
        tmp.push_back(calcmax(tmp));
        ans[i] = tmp[i];
    }
    pre_val = new_val = calc_score_init();
    // REP(i, N) {
    //     cerr << "type:" << i << endl;
    //     for (auto x : position[i]) cerr << x << " ";
    //     cerr << endl;
    // }

    // print_space(ans);
    int best_score = pre_val;
    cerr << "initial score:" << pre_val << endl;

    int tm = gain;
    REP(j, N) update_loss(j);
    REP(j, N) tm -= lss[j];
    assert(tm == pre_val);

    while (true) {
        t++;
        if (t % 1000 == 0) {
            // cerr << "score:" << pre_val << endl;
            clock_t end = clock();
            TIME = static_cast<double>(end - start) / CLOCKS_PER_SEC * 1000.0;
            if (TIME > LIMIT) goto END;
        }
        bool sign = xor128() & 1;
        // int sign = xor128()%5;
        int x = xor128() % D, y = xor128() % D;
        while (x == y) y = xor128() % D;
        int mn = min(x, y);
        int z = xor128() % N;
        while (z == ans[x]) z = xor128() % N;
        int jx = ans[x], jy = ans[y];
        // swap
        if (sign) {
            // if (!position[jx].count(x) || !position[jy].count(y)) fail("swap: cannot erase");
            position[jx].erase(x);
            position[jy].erase(y);
            // if (position[jx].count(y) || position[jy].count(x)) fail("swap: cannot insert");

            position[jx].insert(y);
            position[jy].insert(x);
            swap(ans[x], ans[y]);
            // update gain
            gain = gain - (S[x][jx] + S[y][jy]) + (S[x][jy] + S[y][jx]);
            // new_val = calc_score(ans);
            update_loss(jx);
            update_loss(jy);
            new_val = gain;
            REP(j, N) new_val -= lss[j];
        }
        // update
        else {
            // if (!position[jx].count(x)) fail("update: cannot erase");
            position[jx].erase(x);
            // if (position[z].count(x)) fail("update: cannot insert");
            position[z].insert(x);
            ans[x] = z;
            update_loss(jx);
            update_loss(z);
            gain = gain - S[x][jx] + S[x][z];
            new_val = gain;
            REP(j, N) new_val -= lss[j];
        }
        // temp*=0.999995;
        temp = start_temp + m * TIME;
        double prob = exp((new_val - pre_val) / temp);
        // if too bad
        if (new_val < pre_val - 1000000000) {
            if (sign) {
                jx = ans[x], jy = ans[y];
                if (!position[jx].count(x) || !position[jy].count(y)) fail("swap: cannot erase");
                position[jx].erase(x);
                position[jy].erase(y);
                if (position[jx].count(y) || position[jy].count(x)) fail("swap: cannot insert");
                position[jx].insert(y);
                position[jy].insert(x);
                update_loss(jx);
                update_loss(jy);
                swap(ans[x], ans[y]);
                gain = gain - (S[x][jx] + S[y][jy]) + (S[x][jy] + S[y][jx]);
            } else {
                gain = gain - S[x][z] + S[x][jx];
                ans[x] = jx;

                position[z].erase(x);
                position[jx].insert(x);
                update_loss(jx);
                update_loss(z);
            }
        } else if (new_val > pre_val || prob > (xor128() % INF) / (double)INF) {
            // if(!sign)calc_score_init(ans);
            pre_val = new_val;
            if (new_val > best_score) {
                best_score = new_val;
                REP(i, D) ret[i] = ans[i];
            }
            // chmax(best_score, new_val);
            accepted++;
            continue;
        } else {
            if (sign) {
                jx = ans[x], jy = ans[y];
                position[jx].erase(x);
                position[jy].erase(y);
                position[jx].insert(y);
                position[jy].insert(x);
                update_loss(jx);
                update_loss(jy);
                swap(ans[x], ans[y]);

                gain = gain - (S[x][jx] + S[y][jy]) + (S[x][jy] + S[y][jx]);
            } else {
                gain = gain - S[x][z] + S[x][jx];
                ans[x] = jx;

                position[z].erase(x);
                position[jx].insert(x);
                update_loss(jx);
                update_loss(z);
            }
        }
    }
END:;
    cerr << "temp:" << temp << endl;
    cerr << "accepted:" << (double)accepted / t << endl;
    cerr << "iteration:" << t << '\n';
    cerr << "score:" << best_score << '\n';

    // output
    REP(i, D) { print(ret[i] + 1); }
}

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

    // int q;
    // cin >> q;
    // while (q--)
    solve();
}


Measured memory_bytes: 4616