use proconio::input;
use rand::prelude::*;
use rand::{Rng, SeedableRng};
use std::collections::BTreeSet;

struct Timer {
    start_time: f64,
}

impl Timer {
    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
    }

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

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

struct State {
    base_score: i64,
    schedule: Vec<BTreeSet<i64>>,
    contests: Vec<u64>,
}

impl State {
    fn new(days: u64, sats: &Vec<Vec<i64>>, contests: Vec<u64>) -> Self {
        let mut base_score = 0;
        let mut schedule = vec![BTreeSet::<i64>::new(); 26];

        for day in 0usize..(days as usize) {
            let contest = contests[day as usize] as usize;
            base_score += sats[day][contest] as i64;
            schedule[contest].insert(day as i64);
        }

        State {
            base_score,
            schedule,
            contests,
        }
    }

    fn score(&self, days: i64, cs: &Vec<i64>) -> i64 {
        let mut score = self.base_score;

        for i in 0..cs.len() {
            let mut last = -1;

            for d in self.schedule[i].iter() {
                let x = d - last;
                let n = (x * (x - 1)) / 2;
                score -= cs[i] * n;
                last = *d;
            }
            let x = days - last;
            let n = (x * (x - 1)) / 2;
            score -= cs[i] * n;
        }

        score
    }
}

fn swap_schedule(sats: &Vec<Vec<i64>>, state: &mut State, day_a: usize, day_b: usize) {
    let contest_a = state.contests[day_a as usize] as usize;
    let contest_b = state.contests[day_b as usize] as usize;

    state.base_score -= sats[day_a][contest_a];
    state.base_score -= sats[day_b][contest_b];
    state.base_score += sats[day_a][contest_b];
    state.base_score += sats[day_b][contest_a];

    state.schedule[contest_a].remove(&(day_a as i64));
    state.schedule[contest_b].remove(&(day_b as i64));
    state.schedule[contest_a].insert(day_b as i64);
    state.schedule[contest_b].insert(day_a as i64);

    // Swap contests at the end
    state.contests[day_a as usize] = contest_b as u64;
    state.contests[day_b as usize] = contest_a as u64;
}

fn main() {
    let timer = Timer::new();

    input! { days: u64 };
    let mut cs = vec![0; 26];

    for i in 0..26 {
        input! {
            x: i64
        };

        cs[i] = x;
    }

    let mut sats = vec![vec![0; 26]; days as usize];
    for d in 0..days {
        for i in 0..26 {
            input! {
                s: i64
            };

            sats[d as usize][i as usize] = s;
        }
    }

    let mut ts = vec![0u64; days as usize];
    for i in 0..ts.len() {
        ts[i] = (i as u64) % 26;
    }

    let mut state = State::new(days, &sats, ts);
    let mut cur_score = state.score(days as i64, &cs);

    let seed = [1u8; 32];
    let mut rng: StdRng = SeedableRng::from_seed(seed);

    let start_temp: f64 = 5000.0;
    let end_temp: f64 = 10.0;

    let mut loop_count = 0;

    const TIME_LIMIT_SEC: f64 = 1.98;
    let mut temperture = start_temp;

    let max_move = 30;
    let mut move_range = max_move;
    loop {
        loop_count += 1;

        if loop_count % 100 == 0 {
            let cur_time = timer.get_elapsed_time_sec();
            if cur_time > TIME_LIMIT_SEC {
                break;
            }
            temperture = start_temp + (end_temp - start_temp) * cur_time / TIME_LIMIT_SEC;

            move_range =
                (max_move as f64 + (1.0 - max_move as f64) * cur_time / TIME_LIMIT_SEC) as usize;
        }

        let mut day_a = 0;
        let mut day_b = std::usize::MAX;
        while day_b >= days as usize {
            day_a = rng.gen::<usize>() % (days - 1) as usize;
            day_b = day_a + ((rng.gen::<usize>() % (move_range * 2)) - move_range);
        }

        swap_schedule(&sats, &mut state, day_a, day_b);
        let next_score = state.score(days as i64, &cs);

        let prob = ((next_score - cur_score) as f64 / temperture).exp();

        if prob > rng.gen_range(0.0, 1.0) {
            cur_score = next_score;
        } else {
            swap_schedule(&sats, &mut state, day_a, day_b);
        }
    }

    eprintln!("base_score: {}", state.base_score);
    eprintln!("total: {}", state.score(days as i64, &cs));

    for t in state.contests {
        println!("{}", t + 1);
    }
}


Measured memory_bytes: 3372