#include <algorithm>
#include <chrono>
#include <cstdio>
#include <deque>
#include <iomanip>
#include <iostream>
#include <queue>
#include <random>
#include <stack>
#include <utility>
#include <vector>
#include <fstream>
using std::cin;
using std::cout;
using std::endl;

using namespace std;

using lint=int64_t;
using uint=uint32_t;
using ulint=uint64_t;



class Timer {
  std::chrono::system_clock::time_point start_time_;

public:
  // restart the clock.
  void restart(void) {
    start_time_ = std::chrono::system_clock::now();
  }
  // When instantced, this timer restart itself automatically.
  Timer(void) {
    restart();
  }
  // Get the lap time(milliseconds).
  long long LapTime_millisec(void) {
    auto lap_time = std::chrono::system_clock::now();
    auto dur      = lap_time - start_time_;
    auto msec =
           std::chrono::duration_cast<std::chrono::milliseconds>(dur).count();
    return msec;
  }
  // Get the lap time(seconds).
  long long LapTime_sec(void) {
    auto lap_time = std::chrono::system_clock::now();
    auto dur      = lap_time - start_time_;
    auto sec = std::chrono::duration_cast<std::chrono::seconds>(dur).count();
    return sec;
  }
};

class RandomIntNumber {
  std::mt19937_64 mt_maker_;
  std::uniform_int_distribution<int64_t> range_maker_;

public:
  RandomIntNumber(int64_t min, int64_t max) {
    std::random_device seed_maker;
    mt_maker_.seed(seed_maker());
    // range_maker_.min = min;
    // range_maker_.max = max;
    std::uniform_int_distribution<int64_t>::param_type param(min, max);
    range_maker_.param(param);
  }
  int64_t Make(void) {
    return range_maker_(mt_maker_);
  }
  int64_t operator()(void) {
    return Make();
  }
};

class RandomRealNumber {
  std::mt19937_64 mt_maker_;
  std::uniform_real_distribution<double> range_maker_;

public:
  RandomRealNumber(double min, double max) {
    std::random_device seed_maker;
    mt_maker_.seed(seed_maker());
    // range_maker_.min = min;
    // range_maker_.max = max;
    std::uniform_real_distribution<double>::param_type param(min, max);
    range_maker_.param(param);
  }

  double Make(void){
    return range_maker_(mt_maker_);
  }
  double operator()(void) {
    return Make();
  }
};

bool MoveToNext(const lint next_score,const lint curr_score,const double temperature,const bool maximize, RandomRealNumber& rand_real){
  lint delta=next_score-curr_score;
  if(!maximize){
    delta=-delta; // この処理をした時点で，deltaが正ならより良い結果
  }

  if(delta>=0){
    return true;
  }else{
    return exp(delta/temperature)<rand_real.Make();
  }

}

double GetTemperature(int curr_time_ms, int limit_time_ms, double temp_begin, double temp_end){
  double t=curr_time_ms/(double)limit_time_ms;
  return pow(temp_begin,1-t)*pow(temp_end,t);
}

struct Param{
    double temp_begin=100;
    double temp_end=0;
    //TODO: 必要があれば新たにパラメータを作成
  };

struct State{
  //TODO: 作成
  vector<int> type;
  /// \brief 初期状態のStateを作成
  void InitState(){
    //TODO: 実装
    RandomIntNumber randint(1,26);
    type.resize(366);
    for(int i=1;i<=365;i++){
      type[i]=randint();
    }
  }
  /// \brief 現在のstateからscoreを得る
  /// \return score
  lint CalcScore(vector<int>& c, vector<vector<int>>& s){
    //TODO: 実装
    lint result=0;
    vector<int> last(27, 0);
    for(int d=1;d<=365;d++){
      result+=s[d][type[d]];
      last[type[d]]=d;
      for(int i=1;i<=26;i++){
        result-=c[i]*(d-last[i]);
      }
    }
    return result;
  }
};

int main(int argc, char* argv[]){
  bool is_optimize=(argc>1);
  Timer timer;
  RandomRealNumber rand_real(0,1);
  RandomIntNumber rand_int_365(1, 365);
  RandomIntNumber rand_int_pm10(-10, 10);
  RandomIntNumber rand_int_26(1,26);

  //TODO: コンテストに合わせて適当に調整
  /// \brief 何回のループごとに時間確認・冷却するか
  const int TIME_CHECK_FREQ=100;
  /// \brief 制限時間
  const int LIMIT_TIME_MS=2000;
  /// \brief 時間確認時に残り時間がこれ以下だったら終了
  const int TIME_MARGIN=20;
  /// \brief 最大化問題ならtrue
  const bool MAXIMIZE=true;

  Param param;
  //TODO: 標準入力からテストケースを受け取る
  int d;
  cin>>d;
  vector<int> c(27);
  vector<vector<int>> s(d+1, vector<int>(27));

  for(int i=1;i<=26;i++){
    cin>>c[i];
  }

  for(int i=1;i<=d;i++){
    for(int j=1;j<=26;j++){
      cin>>s[i][j];
    }
  }

  if(is_optimize){
    //TODO: パラメータをargvから取得
    param.temp_begin=stod(argv[1]);
    param.temp_end=stod(argv[2]);
  }

  double temperature=param.temp_begin;

  int loop_cnt=0;
  State curr_state=State();
  curr_state.InitState();
  lint curr_score=curr_state.CalcScore(c,s);

  while(true){
    loop_cnt++;
    if(loop_cnt%TIME_CHECK_FREQ==TIME_CHECK_FREQ-1){
      lint laptime=timer.LapTime_millisec();
      if(laptime>=LIMIT_TIME_MS-TIME_MARGIN){
        if(is_optimize){
          cout<<curr_score<<endl;
        }else{
          for(int i=1;i<=d;i++){
            cout<<curr_state.type[i]<<endl;
          }
          cerr<<curr_score<<endl;
        }
        return 0;
      }else{
        temperature=GetTemperature(laptime,LIMIT_TIME_MS,param.temp_begin, param.temp_end);
      }
    }

    // TODO: これ以降のコードを実装
    // 現在の状態を保存

    // 少し変化させる

    pair<int,int> rev_a, rev_b;

    if(rand_real.Make()<0.5){
      // 1点更新
      int tgt=rand_int_365.Make();
      int to=rand_int_26.Make();
      rev_a=make_pair(tgt,curr_state.type[tgt]);
      rev_b=make_pair(-1,-1);
      curr_state.type[tgt]=to;
    }else{
      // swap
      int tgt_a=rand_int_365.Make();
      int tgt_b=rand_int_pm10.Make()+tgt_a;
      tgt_b=min(tgt_b,1);
      tgt_b=max(tgt_b,365);
      rev_a=make_pair(tgt_a,curr_state.type[tgt_a]);
      rev_b=make_pair(tgt_b, curr_state.type[tgt_b]);

      swap(curr_state.type[tgt_a], curr_state.type[tgt_b]);
    }

    // スコア計算 CalcScore()より早い方法があるならそちらを採用．
    lint next_score=curr_state.CalcScore(c,s);

    if(MoveToNext(next_score, curr_score, temperature, MAXIMIZE,rand_real)){
      //curr_stateを次の状態に変更
      curr_score=next_score;
    }else{
      //curr_stateを保存した状態に戻す
      curr_state.type[rev_a.first]=rev_a.second;
      if(rev_b.first!=-1){
        curr_state.type[rev_b.first]=rev_b.second;
      }
    }

  }

}

Measured memory_bytes: 4220