#![allow(non_snake_case)]
use num::clamp;
use proconio::marker::*;
use proconio::*;
use rand::prelude::*;
use std::cmp::max;
use std::cmp::min;
use std::collections::BinaryHeap;
use std::i64;
use std::mem::swap;
use std::thread::sleep;
use std::time::*;

#[derive(Debug)]
struct State {
    D: usize,
    c: Vec<i64>,
    s: Vec<Vec<i64>>,
    t: Vec<usize>,
    lasts: Vec<usize>,
    d: usize,
    score: i64,
}

impl State {
    fn new(D: usize, c: Vec<i64>, s: Vec<Vec<i64>>) -> State {
        State {
            D,
            c,
            s,
            t: vec![0; D],
            lasts: vec![0; 26],
            d: 0,
            score: 0,
        }
    }

    fn set_rand(&mut self) {
        let mut rng = thread_rng();
        for i in 0..self.D {
            self.t[i] = rng.gen_range(0, 26);
        }
    }

    fn set_greed(&mut self) {
        for i in 0..self.D {
            let mut max_score = i64::min_value();
            let mut q = 0;
            for j in 0..26 {
                self.t[i] = j;
                let score = self.calc(i, j);
                if score > max_score {
                    max_score = score;
                    q = j;
                }
            }

            self.lasts[q] = i + 1;
            self.t[i] = q;
        }
    }

    fn set_dfs(&mut self) {
        let depth = 4;
        for i in 0..self.D {
            let mut max_score = i64::min_value();
            let mut q = 0;
            for j in 0..26 {
                let score = self.dfs(i, j, depth, 0);
                if score > max_score {
                    max_score = score;
                    q = j;
                }
            }

            self.lasts[q] = i + 1;
            self.t[i] = q;
        }
    }

    fn dfs(&mut self, d: usize, q: usize, depth: usize, cur_score: i64) -> i64 {
        if depth == 0 || d == self.D {
            return 0;
        }

        let mut heap = BinaryHeap::with_capacity(26);
        let mut max_score = i64::min_value();
        let cur_score = cur_score + self.calc(d, q);
        let last = self.lasts[q];
        self.lasts[q] = d + 1;

        for i in 0..26 {
            let score = self.calc(d, i);
            heap.push((i, score));
        }

        for &(i, _) in heap.iter().take(2) {
            max_score = max(max_score, self.dfs(d + 1, i, depth - 1, cur_score));
        }

        self.lasts[q] = last;
        max_score + cur_score
    }

    fn calc(&mut self, d: usize, q: usize) -> i64 {
        let mut score = self.s[d][q];
        let last = self.lasts[q];

        self.lasts[q] = d + 1;
        for i in 0..26 {
            score -= (d + 1 - self.lasts[i]) as i64 * self.c[i];
        }

        self.lasts[q] = last;

        score
    }

    fn result(&self) -> i64 {
        let mut score = 0;
        let mut lasts = vec![0; 26];
        for d in 0..self.D {
            score += self.s[d][self.t[d]];
            let l = lasts[self.t[d]];
            lasts[self.t[d]] = d + 1;
            score -= self.c[self.t[d]] * ((d - l) * (d - l + 1) / 2) as i64;
        }

        for i in 0..26 {
            let l = lasts[i];
            score -= self.c[i] * ((self.D - l) * (self.D - l + 1) / 2) as i64;
        }

        score
    }
}

fn main() {
    input! {
        D: usize,
        c: [i64; 26],
        s: [[i64; 26]; D],
    };
    let mut obj = State::new(D, c, s);
    let mut rng = thread_rng();
    let time = SystemTime::now();
    obj.set_dfs();
    let mut max_score = obj.result();

    loop {
        let d1 = rng.gen_range(0, D);
        let d2 = min(rng.gen_range(d1.saturating_sub(2), d1 + 3), D - 1);

        obj.t.swap(d1, d2);
        let score = obj.result();
        if score > max_score {
            max_score = score;
        } else {
            obj.t.swap(d1, d2);
        }

        if time.elapsed().unwrap().as_millis() > 1950 {
            break;
        }
    }

    for &t in &obj.t {
        println!("{}", t + 1);
    }
}


Measured memory_bytes: 2660