#![allow(non_snake_case)]

use std::io::{BufRead, BufReader, Read};

use rand::prelude::*;
use rand_pcg::Pcg64Mcg;

const ALPHA_SIZE: usize = 26;
const TIME_LIMIT: f64 = 1.8;

pub trait SetMinMax {
    fn set_min(&mut self, v: Self) -> bool;
    fn set_max(&mut self, v: Self) -> bool;
}

impl<T> SetMinMax for T where T: PartialOrd {
    fn set_min(&mut self, v: Self) -> bool {
        *self > v && {
            *self = v;
            true
        }
    }

    fn set_max(&mut self, v: Self) -> bool {
        *self < v && {
            *self = v;
            true
        }
    }
}

struct Timer {
    start_time: f64
}

fn get_time_sec() -> f64 {
    let t = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap();
    t.as_secs() as f64 + t.subsec_nanos() as f64 * 1e-9
}

impl Timer {
    fn new() -> Timer {
        Timer {
            start_time: get_time_sec()
        }
    }

    fn get_elapsed_time_sec(self: &Self) -> f64 {
        get_time_sec() - self.start_time
    }
}


#[derive(Clone)]
struct State<'a> {
    D: usize,
    C: &'a Vec<i32>,
    S: &'a Vec<Vec<i32>>,
    actions: Vec<usize>,
    next_same: Vec<usize>,
    prev_same: Vec<usize>,
    score: i32,
}

fn compute_score(C: &Vec<i32>, S: &Vec<Vec<i32>>, actions: &Vec<usize>) -> i32 {
    let mut score = 0;
    let mut last: Vec<i32> = vec![-1; ALPHA_SIZE];
    for d in 0..actions.len() {
        let diff = d as i32 - last[actions[d]];
        score += S[d][actions[d]];
        score -= diff * (diff - 1) / 2 * C[actions[d]];
        last[actions[d]] = d as i32;
    }
    for c in 0..ALPHA_SIZE {
        let diff = actions.len() as i32 - last[c];
        score -= diff * (diff - 1) / 2 * C[c]
    }
    score
}

fn compute_prev_next(actions: &Vec<usize>) -> (Vec<usize>, Vec<usize>) {
    let mut next_same = vec![actions.len() + 1; actions.len()];
    let mut prev_same = vec![0; actions.len()];
    let mut last = vec![0; ALPHA_SIZE];
    for d in 0..actions.len() {
        if last[actions[d]] > 0 {
            next_same[last[actions[d]] - 1] = d + 1;
            prev_same[d] = last[actions[d]];
        }
        last[actions[d]] = d + 1;
    }
    (prev_same, next_same)
}

fn cost(d1: usize, d2: usize) -> i32 {
    assert!(d1 < d2);
    let diff = (d2 - d1) as i32;
    return diff * (diff - 1) / 2;
}

impl<'a> State<'a> {
    fn create(D: usize, C: &'a Vec<i32>, S: &'a Vec<Vec<i32>>, actions: Vec<usize>) -> State<'a> {
        assert_eq!(actions.len(), D);
        assert_eq!(S[0].len(), ALPHA_SIZE);
        let score = compute_score(C, S, &actions);
        let (prev_same, next_same) = compute_prev_next(&actions);
        return State { D, C, S, actions, next_same, prev_same, score };
    }




    fn change_action(self: &mut Self, date: usize, action: usize) {
        if action == self.actions[date] {
            return;
        }

        let curr_action = self.actions[date];
        let next_same = self.next_same[date];
        let prev_same = self.prev_same[date];

        self.score += (cost(prev_same, date + 1) + cost(date + 1, next_same) - cost(prev_same, next_same)) * self.C[curr_action];
        self.score -= self.S[date][curr_action];
        if prev_same > 0 {
            self.next_same[prev_same - 1] = next_same;
        }
        if next_same <= self.D {
            self.prev_same[next_same - 1] = prev_same;
        }

        let mut new_prev_same = date;
        while new_prev_same > 0 && self.actions[new_prev_same - 1] != action {
            new_prev_same -= 1;
        }
        let new_next_same = if new_prev_same > 0 {
            self.next_same[new_prev_same - 1]
        } else {
            let mut next_same = date + 2;
            while next_same <= self.D && self.actions[next_same - 1] != action {
                next_same += 1;
            }
            next_same
        };

        // dbg!(new_prev_same, new_next_same, date);
        self.score -= (cost(new_prev_same, date + 1) + cost(date + 1, new_next_same) - cost(new_prev_same, new_next_same)) * self.C[action];
        self.score += self.S[date][action];
        if new_prev_same > 0 {
            self.next_same[new_prev_same - 1] = date + 1;
        }
        if new_next_same <= self.D {
            self.prev_same[new_next_same - 1] = date + 1;
        }
        self.prev_same[date] = new_prev_same;
        self.next_same[date] = new_next_same;
        self.actions[date] = action;
        // let (prev, next) = compute_prev_next(&self.actions);
        // dbg!(action, curr_action, &self.actions);
        // assert_eq!(prev, self.prev_same);
        // assert_eq!(next, self.next_same);
    }

    fn swap_actions(self: &mut Self, d1: usize, d2: usize) {
        let action = self.actions[d1];
        self.change_action(d1, self.actions[d2]);
        self.change_action(d2, action);
    }
}

struct Solver {
    D: usize,
    C: Vec<i32>,
    S: Vec<Vec<i32>>,
    timer: Timer,
}

impl Solver {
    fn create(input: &mut dyn Read) -> Solver {
        let mut buffer = String::new();
        input.read_to_string(&mut buffer).unwrap();
        let mut iter = buffer.split_whitespace();
        let D = iter.next().unwrap().parse::<usize>().unwrap();

        let C: Vec<i32> = (0..ALPHA_SIZE)
            .map(|_| iter.next().unwrap().parse::<i32>().unwrap())
            .collect();
        let S: Vec<Vec<i32>> = (0..D)
            .map(|_| {
                (0..ALPHA_SIZE)
                    .map(|_| iter.next().unwrap().parse::<i32>().unwrap())
                    .collect()
            })
            .collect();
        Solver { D, C, S, timer: Timer::new() }
    }

    fn annealing_update(old_score: i32, new_score: i32, temperature: f64, rng: &mut Pcg64Mcg) -> bool {
        let diff = new_score - old_score;
        diff > 0 || rng.gen_bool(f64::exp(diff as f64 / temperature))
    }

    fn annealing(self: &Self, initial_actions: Vec<usize>) -> Vec<usize> {
        const T_MAX: f64 = 2000.;
        const T_MIN: f64 = 600.;
        let mut temperature = T_MAX;
        let mut rng = rand_pcg::Pcg64Mcg::new(1);
        let mut state = State::create(self.D, &self.C, &self.S, initial_actions.clone());
        let mut loop_count = 0;
        let mut update_count = 0;
        let mut best_score = state.score;
        let mut curr_score = best_score;
        let mut best_actions = initial_actions;
        let swap_prob = 0.5;
        let swap_max_offset = 13;
        let mut change_type = 0;

        loop {
            loop_count += 1;
            if loop_count % 100 == 0 {
                let t = self.timer.get_elapsed_time_sec() / TIME_LIMIT;
                if t >= 1. {
                    break;
                } else {
                    temperature = T_MAX.powf(1.0 - t) * T_MIN.powf(t);
                }
            }

            if rng.gen_bool(swap_prob) {
                let d1 = rng.gen_range(0, self.D - 1);
                let d2 = rng.gen_range(d1 + 1, (d1 + swap_max_offset).min(self.D));
                state.swap_actions(d1, d2);
                if Solver::annealing_update(curr_score, state.score, temperature, &mut rng) {
                    change_type = 1;
                    curr_score = state.score;
                } else {
                    state.swap_actions(d1, d2);
                }
            } else {
                let d = rng.gen_range(0, self.D);
                let a = rng.gen_range(0, ALPHA_SIZE);
                let curr_action = state.actions[d];
                state.change_action(d, a);
                if Solver::annealing_update(curr_score, state.score, temperature, &mut rng) {
                    change_type = 2;
                    curr_score = state.score;
                } else {
                    state.change_action(d, curr_action)
                }
            }

            if best_score.set_max(curr_score) {
                eprintln!("[{} / {}] Change the best score to {} (time = {}, change_type = {})",
                          update_count, loop_count, best_score, self.timer.get_elapsed_time_sec(), change_type);
                best_score = curr_score;
                best_actions = state.actions.clone();
                update_count += 1;
            }
        }
        best_actions
    }

    fn hill_climbing(self: &Self, start_state: Vec<usize>) -> Vec<usize> {
        let mut state = State::create(self.D, &self.C, &self.S, start_state);
        let mut update_count = 0;
        let mut best_score = state.score;
        eprintln!("Start from {}", best_score);

        loop {
            let mut has_update = false;
            for d in 0..self.D {
                for a in 0..ALPHA_SIZE {
                    let old_score = state.score;
                    let curr_action = state.actions[d];
                    state.change_action(d, a);
                    let new_score = state.score;
                    if best_score.set_max(new_score) {
                        eprintln!("[{}: Modify] Change best score from {} to {} (time = {})",
                                  update_count, best_score, new_score, self.timer.get_elapsed_time_sec());
                        has_update = true;
                        update_count += 1;
                    } else {
                        state.change_action(d, curr_action);
                        assert_eq!(state.score, old_score)
                    }
                }
            }

            for d1 in 0..self.D - 1 {
                for d2 in d1 + 1..self.D {
                    let old_score = state.score;
                    state.swap_actions(d1, d2);
                    let new_score = state.score;
                    if best_score.set_max(new_score) {
                        eprintln!("[{}: Swap] Change best score from {} to {} (time = {})",
                                  update_count, best_score, new_score, self.timer.get_elapsed_time_sec());
                        has_update = true;
                        update_count += 1;
                        break;
                    } else {
                        state.swap_actions(d1, d2);
                        assert_eq!(state.score, old_score)
                    }
                }
            }

            if !has_update {
                break;
            }
        }
        state.actions
    }

    pub fn solve(self: &Self) -> Vec<usize> {
        let mut rng = rand_pcg::Pcg64Mcg::new(1);
        let start_actions = (0..self.D).map(|_| rng.gen_range(0, ALPHA_SIZE)).collect();
        self.hill_climbing(self.annealing(start_actions))
        // self.annealing(start_actions)
    }
}

fn main() {
    // let args: Vec<String> = env::args().collect();
    // let mut opts = Options::new();
    // opts.optopt("f", "file", "Input file", "FILE");
    // let matches = match opts.parse(&args[1..]) {
    //     Ok(m) => { m }
    //     Err(f) => { panic!(f.to_string()) }
    // };

    // let mut input: Box<dyn BufRead> = if matches.opt_present("f") && false {
    //     Box::new(BufReader::new(File::open(matches.opt_str("f").unwrap()).unwrap()))
    // } else {
    //     Box::new(BufReader::new(std::io::stdin()))
    // };
    // let mut input: Box<dyn BufRead> = Box::new(BufReader::new(File::open("./tester/1.in").unwrap()));
    let mut input: Box<dyn BufRead> = Box::new(BufReader::new(std::io::stdin()));
    let solver = Solver::create(& mut input);
    for action in solver.solve() {
        println!("{}", action + 1);
    }
}


Measured memory_bytes: 3340