#include <iostream>
#include <vector>
#include <ctime>
#include <algorithm>
using namespace std;

const int WIDTH = 16300;
const int DEBUG = 0;

struct State {
	int score;
	int prevs;
	int sousa;
	int genten;
	int Last[27];
};

struct State2 {
	int score, num;
};

bool operator<(const State& a1, const State& a2) {
	if (a1.score < a2.score) return true;
	return false;
}

bool operator<(const State2& a1, const State2& a2) {
	if (a1.score < a2.score) return true;
	return false;
}

int N;
int C[29], S[409][29];
int cnts[409];
int Last[409];
int BORDER;
State G[409][WIDTH + 9];
State H[(WIDTH * 26) + 9];
State2 I[(WIDTH * 26) + 9];

int getscore(vector<int> vec) {
	for (int i = 1; i <= 26; i++) Last[i] = 0;
	int t = 0;
	for (int i = 0; i < vec.size(); i++) {
		Last[vec[i]] = i + 1; t += S[i + 1][vec[i]];
		for (int j = 1; j <= 26; j++) t -= C[j] * ((i + 1) - Last[j]);
	}
	return t;
}

void getGenten(int pos) {
	for (int i = 0; i < cnts[pos]; i++) {
		for (int j = 1; j <= 26; j++) G[pos][i].genten += C[j] * ((pos + 1) - G[pos][i].Last[j]);
	}
}

void solve(int pos, int num, int i, int news) {
	H[cnts[pos + 1]].score = news;
	H[cnts[pos + 1]].prevs = num;
	H[cnts[pos + 1]].sousa = i;
	for (int j = 1; j <= 26; j++) H[cnts[pos + 1]].Last[j] = G[pos][num].Last[j];
	H[cnts[pos + 1]].Last[i] = pos + 1;
	cnts[pos + 1]++;
}

int main() {
	// 入力
	if (DEBUG == 0) {
		cin >> N;
		for (int i = 1; i <= 26; i++) cin >> C[i];
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= 26; j++) cin >> S[i][j];
		}
	}
	else {
		N = 365;
		for (int i = 1; i <= 26; i++) C[i] = rand() % 101;
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= 26; j++) S[i][j] = ((rand() % 32768) * 32768 + (rand() % 32768)) % 20001;
		}
	}

	// ビームサーチ
	G[0][0].prevs = -1; cnts[0] = 1;
	for (int i = 0; i < N; i++) {
		// 前処理
		getGenten(i);

		// 適当に 2000 個サンプリングする
		BORDER = -(1 << 28); vector<int> R;
		for (int t = 0; t < 2000; t++) {
			int r1 = rand() % cnts[i], r2 = (rand() % 26) + 1;
			int NewScore = G[i][r1].score;
			NewScore += S[i + 1][r2];
			NewScore -= G[i][r1].genten;
			NewScore += C[r2] * ((i + 1) - G[i][r1].Last[r2]);
			R.push_back(NewScore);
		}
		sort(R.begin(), R.end());
		reverse(R.begin(), R.end());
		if (cnts[i] == WIDTH) BORDER = R[111];
		else BORDER = -(1 << 28);

		// 枝刈りする
		cnts[i + 1] = 0;
		for (int j = 0; j < cnts[i]; j++) {
			for (int k = 1; k <= 26; k++) {
				int NewScore = G[i][j].score;
				NewScore += S[i + 1][k];
				NewScore -= G[i][j].genten;
				NewScore += C[k] * ((i + 1) - G[i][j].Last[k]);
				if (NewScore >= BORDER) solve(i, j, k, NewScore);
			}
		}
		for (int j = 0; j < cnts[i + 1]; j++) I[j] = State2{ H[j].score, j };

		// ソート
		sort(I, I + cnts[i + 1]);
		reverse(I, I + cnts[i + 1]);
		cnts[i + 1] = min(cnts[i + 1], WIDTH);
		for (int j = 0; j < cnts[i + 1]; j++) G[i + 1][j] = H[I[j].num];
	}

	// 復元
	vector<int> Answer; int cx = 0;
	for (int i = N; i >= 1; i--) {
		Answer.push_back(G[i][cx].sousa);
		cx = G[i][cx].prevs;
	}
	reverse(Answer.begin(), Answer.end());

	// 山登り法
	vector<int> R;
	for (int i = 1; i <= N; i++) R.push_back(Answer[i - 1]);
	int CurrentMax = getscore(R), S = 0;
	for (int t = 1; t <= 80000; t++) {
		if (rand() % 10 < 6) {
			int v1 = 10000, v2 = 10000;
			while (v1 + v2 >= N) { v1 = rand() % N; v2 = rand() % 20; }
			swap(R[v1], R[v2]);
			int CandMax = getscore(R);
			if (CurrentMax <= CandMax) { CurrentMax = CandMax; S = 0; }
			else { swap(R[v1], R[v2]); S += 1; }
		}
		else {
			int v1 = rand() % N, v2 = rand() % 26 + 1;
			int moto = R[v1];
			R[v1] = v2;
			int CandMax = getscore(R);
			if (CurrentMax <= CandMax) { CurrentMax = CandMax; S = 0; }
			else { R[v1] = moto; S += 1; }
		}
	}
	for (int i = 1; i <= N; i++) cout << R[i - 1] << endl;
	return 0;
}

Measured memory_bytes: 724768