// #define _GLIBCXX_DEBUG // for STL debug (optional)
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <cfloat>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <fstream>
#include <functional>
#include <bitset>
#include <chrono>
#include <random>
using namespace std;
using ll = long long int;
using int64 = long long int;
 
template<typename T> void chmax(T &a, T b) {a = max(a, b);}
template<typename T> void chmin(T &a, T b) {a = min(a, b);}
template<typename T> void chadd(T &a, T b) {a = a + b;}
 
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
const int INF = 1LL << 29;
const ll LONGINF = 1LL << 60;
const ll MOD = 1000000007LL;

// [lb, ub] の閉区間内の値をランダムに返す構造体
// #include <random> しよう

struct Rand {
public:
    Rand() = default;
    Rand(std::mt19937::result_type seed) : eng(seed) {}
    int NextInt(int lb, int ub) {
        return std::uniform_int_distribution<int>{lb, ub}(eng);
    }
    ll NextLong(ll lb, ll ub) {
        return std::uniform_int_distribution<ll>{lb, ub}(eng);
    }
    double NextDouble(double lb, double ub) {
        return std::uniform_real_distribution<double>{lb, ub}(eng);
    }
private:
    std::mt19937 eng{std::random_device{}()};
};

/* 
// example.
int main() {
    Rand rnd(114514);
    int l, r; scanf("%d%d", &l, &r);
    printf("l = %d, r = %d, value = %d\n", l, r, rnd.NextInt(l, r));

    double L, R; scanf("%lf%lf", &L, &R);
    printf("L = %.12f, R = %.12f, value = %.12f\n", L, R, rnd.NextDouble(L, R));

    long long int a, b; scanf("%lld%lld", &a, &b);
    printf("a = %lld, b = %lld, value = %lld\n", a, b, rnd.NextLong(a, b));
    return 0;
}
*/

class Timer {
    chrono::high_resolution_clock::time_point start, end;
    double limit;

public:
    Timer() {
        start = chrono::high_resolution_clock::now();
    }
    Timer(double l) {
        start = chrono::high_resolution_clock::now();
        limit = l;
    }

    double getTime() {
        end = chrono::high_resolution_clock::now();
        return chrono::duration<double>(end - start).count();
    }

    bool isTimeOver() {
        if (getTime() > limit) {
            return true;
        }
        return false;
    }

    double getLimit() { return limit; }
    void setLimit(double l) {
        limit = l;
    }
    void setStart() { start = chrono::high_resolution_clock::now(); }
};

const int DAY = 365;
const int CONT = 26;
Rand rnd(1333);

struct Solver {
    int D, C[CONT], S[DAY][CONT], ans[DAY], best_ans[DAY];
    ll score, best_score, update_iter;
    set<int> schedules[CONT];
    ll interval_len_add[CONT], optimal_day_add[CONT];
    ll interval_len_del[CONT], optimal_day_del[CONT];
    
    Solver() {
        update_iter = 0;
        fill(ans, ans + DAY, -1);
        fill(interval_len_add, interval_len_add + CONT, -1);
        fill(optimal_day_add, optimal_day_add + CONT, -1);
    }
    
    void read_input() {
        scanf("%d", &D);
        for(int i=0; i<CONT; i++) {
            scanf("%d", &C[i]);
        }
        for(int i=0; i<D; i++) {
            for(int j=0; j<CONT; j++) {
                scanf("%d", &S[i][j]);
            }
        }

        for(int i=0; i<CONT; i++) {
            schedules[i].emplace(-1);
            schedules[i].emplace(D);
        }
    }

    void set_random() {
        for(int i=0; i<D; i++) {
            ans[i] = rnd.NextInt(1, CONT) - 1;
            schedules[ ans[i] ].emplace(i);
            best_ans[i] = ans[i];
        }
    }

    void set_greedy() {
        ll score_greedy = 0;
        int last[CONT] = {};
        for(int i=0; i<D; i++) {
            ll max_cand = -LONGINF, argmax = -1;
            for(int j=0; j<CONT; j++) {
                ll cand = score_greedy + S[i][j];
                for(int k=0; k<CONT; k++) {
                    if(j == k) continue;
                    cand -= ((i+1) - last[k]) * C[k];
                }
                if(max_cand < cand) {
                    max_cand = cand;
                    argmax = j;
                }
            }
            ans[i] = argmax;
            schedules[ ans[i] ].emplace(i);
            best_ans[i] = ans[i];
            last[argmax] = i;
            score_greedy = max_cand;
        }
    }
    
    int update_optimal_day(int contest, bool verbose=false) {
        interval_len_add[contest] = -1;
        optimal_day_add[contest] = -1;
        auto itr = schedules[contest].begin();
        for(; *itr!=D; itr++) {
            int l = *itr, r = *next(itr);
            int len_add = r - l - 1;
            ll s = len_add * (len_add + 1) / 2 * C[contest];
            if(verbose) fprintf(stderr, "s = %lld\n", s);
            if(interval_len_add[contest] < s) {
                interval_len_add[contest] = s;
                optimal_day_add[contest] = max(0, l + (len_add + 1) / 2);
            }
        }
        return interval_len_add[contest];
    }

    ll calc_score(bool store=true) {
        ll res = 0;
        int last[CONT] = {};
        for(int i=0; i<D; i++) {
            res += S[i][ ans[i] ];
            last[ ans[i] ] = i+1;
            for(int j=0; j<CONT; j++) {
                res -= C[j] * (i+1 - last[j]);
            }
        }
        if(store) score = res;
        return res;
    }

    void update(int day, int contest) {
        int pre_contest = ans[day];
        ans[day] = contest;

        // 削除
        {
            score -= S[day][pre_contest];
            // assert(schedules[pre_contest].count(day));
            auto ptr = schedules[pre_contest].lower_bound(day);
            ll d0 = day - *prev(ptr);
            ll d1 = *next(ptr) - *prev(ptr);
            ll d2 = *next(ptr) - day;
            score += d0 * (d0 - 1) / 2 * C[pre_contest];
            score -= d1 * (d1 - 1) / 2 * C[pre_contest];
            score += d2 * (d2 - 1) / 2 * C[pre_contest];
            schedules[pre_contest].erase(day);
        }
        // 追加
        {
            score += S[day][contest];
            // assert(!schedules[contest].count(day));
            schedules[contest].emplace(day);
            auto ptr = schedules[contest].lower_bound(day);
            ll d0 = day - *prev(ptr);
            ll d1 = *next(ptr) - *prev(ptr);
            ll d2 = *next(ptr) - day;
            score -= d0 * (d0 - 1) / 2 * C[contest];
            score += d1 * (d1 - 1) / 2 * C[contest];
            score -= d2 * (d2 - 1) / 2 * C[contest];
        }
    }

    bool update_best_ans() {
        if(best_score >= score) return false;

        update_iter++;
        best_score = score;
        for(int i=0; i<D; i++) best_ans[i] = ans[i];
        return true;
    }

    void proceed(ll iter) {        
        double prob = rnd.NextInt(1, 10000) / 10000.0;

        ll current_score = score;
        if(prob < 0.5) {
            int d = rnd.NextInt(1, D) - 1;
            int q = rnd.NextInt(1, CONT) - 1;
            int prev_ans = ans[d];
            if(prev_ans == q) return;

            update(d, q);
            if(!update_best_ans()) {
                ans[d] = prev_ans;
                schedules[prev_ans].emplace(d);
                schedules[q].erase(d);
                score = current_score;
            }
        }
        else {
            int W = rnd.NextInt(1, 15);
            int d = rnd.NextInt(1, D-W) - 1;
            int u = ans[d], v = ans[d+W];
            if(u == v) return;
            
            update(d, v);
            update(d+W, u);
            if(!update_best_ans()) {
                ans[d] = u, ans[d+W] = v;
                schedules[u].emplace(d);
                schedules[u].erase(d+W);
                schedules[v].erase(d);
                schedules[v].emplace(d+W);
                score = current_score;
            }
        }
    }
};

int main() {
    Solver solver;
    solver.read_input();

    Timer timer;
    solver.set_greedy();
    // solver.set_random();
    // for(int i=0; i<CONT; i++) solver.update_optimal_day(i);
    
    ll init_score = solver.calc_score(), iter = 0;
    solver.best_score = solver.score;
    fprintf(stderr, "init_score = %lld\n", init_score);
    for(; ; iter++) {
        if(iter % 500 == 0) {
            if(timer.getTime() > 1.95) break;
        }
        solver.proceed(iter);
    }

    ll final_score = solver.best_score;
    fprintf(stderr, "final_score = %lld\n", final_score);
    fprintf(stderr, "iter = %lld, update_iter = %lld\n", iter, solver.update_iter);
    for(int i=0; i<solver.D; i++) {
        printf("%d\n", solver.best_ans[i] + 1);
    }
    return 0;
}


Measured memory_bytes: 3828