#54936: 思路 TOP1


321qwedsa000@gmail.com (灝)


#include <cstdio>

// ============================================================
// TMP 常數
// ============================================================
template <int N> struct Stride   { static constexpr int value = N + 1; };
template <int N> struct OutBuf   { static constexpr int value = N + 2; };

// ============================================================
// 核心:最快讀法
// 對角線元素位於 offset = base + i*(n+1),i=0..n-1
// 連續讀 n 個「每隔 stride 一個」的字元
//
// 最優策略:把 N 個目標位置「打包」成 1 次 fread:
//   讀從 base 到 base+(n-1)*(n+1) 的整段,共 (n-1)*(n+1)+1 bytes
//   但這最大 = 4999*5001+1 ≈ 25MB → 超記憶體
//
// 折衷:分段 fread,每段讀 STRIDE 個字元,取第 0 個
//   每段只需 1 個字元有用,但 fread 系統呼叫次數 = N(最多 5000)
//   → 用更大的 chunk 一次覆蓋多個對角線元素
// ============================================================

// TMP:chunk 要覆蓋幾個對角線元素(編譯期調整)
template <int CoverCount>
struct ChunkPolicy {
    static constexpr int count = CoverCount;  // 一個 chunk 取幾個對角線元素
};

using FastPolicy = ChunkPolicy<64>;  // 一次 fread 覆蓋 64 個對角線元素

// ============================================================
// TMP 主讀取器:一次 fread 一塊,從中萃取多個對角線字元
// chunk_size = cover * stride(最大 64*5001 = 320064 bytes ≈ 312KB)
// ============================================================
template <int Cover>
struct DiagReader {
    // 靜態 buffer:最大 Cover * (MaxN+1) = 64 * 5001 = 320064
    static constexpr int MAX_STRIDE = 5001;
    static constexpr int BUF_SIZE   = Cover * MAX_STRIDE;
    static char buf[BUF_SIZE];

    static void run(int n) {
        int stride = n + 1;
        int chunk  = Cover * stride;  // 一次讀的位元組數

        static char out[5002];
        int oi = 0;
        int remain = n;

        // 跳過第一行(讀取 n 後跳到字串開頭)
        {
            int c;
            while ((c = fgetc(stdin)) != EOF && c != '\n');
            // 現在 stdin 指向字串第一個字元
        }

        while (remain > 0) {
            int take = (remain < Cover) ? remain : Cover;
            int toread = (take - 1) * stride + 1;  // 只讀到最後一個目標字元
            // 但為了對齊,讀整個 chunk(取 cover 個元素)
            // 若剩餘不足一個 chunk,調小
            int got = (int)fread(buf, 1, toread, stdin);
            if (got <= 0) break;

            // 從 buf 中萃取對角線字元:位置 0, stride, 2*stride, ...
            for (int k = 0; k < take; ++k) {
                int pos = k * stride;
                if (pos >= got) break;
                out[oi++] = buf[pos];
                --remain;
            }

            // 跳過這個 chunk 剩餘的字元(下一個對角線元素的前 stride-1 個字元)
            // 已讀到位置 (take-1)*stride,下一個目標在 take*stride
            // 需要跳過: take*stride - toread = stride - 1 個字元
            if (remain > 0) {
                int skip = stride - 1;
                fseek(stdin, skip, SEEK_CUR);
            }
        }

        out[oi++] = '\n';
        fwrite(out, 1, oi, stdout);
    }
};

template <int Cover>
char DiagReader<Cover>::buf[DiagReader<Cover>::BUF_SIZE];

// ============================================================
// main
// ============================================================
int main() {
    int n;
    scanf("%d", &n);
    DiagReader<64>::run(n);
}