#include <iostream>
#include <fstream>
#include <vector>
#include <random>
#include <chrono>
#include <cassert>
#include <algorithm>
#include <numeric>

using namespace std;

// 检查从1能否到达n，并返回可达性
bool can_reach(const vector<int>& a) {
    int n = a.size() - 1; // 下标1..n
    int cur = 1;
    while (cur < n) {
        if (a[cur] == 0) return false;
        int nxt = min(n, cur + a[cur]);
        // 贪心选择最远？这里只是判断是否存在路径，用BFS更准确，但简单判断：能跳到超过n即可
        // 我们简单用BFS
        vector<bool> vis(n+1, false);
        vis[1] = true;
        for (int i = 1; i <= n; ++i) {
            if (!vis[i]) continue;
            for (int j = i+1; j <= min(n, i + a[i]); ++j) vis[j] = true;
        }
        return vis[n];
    }
    return true;
}

// 随机生成一个合法的a数组，保证至少有一条路径
vector<int> generate_random(int n, mt19937& rng) {
    vector<int> a(n+1);
    // 先构造一条主路径：1 -> p1 -> p2 -> ... -> n
    vector<int> path = {1};
    int cur = 1;
    while (cur < n) {
        int step = uniform_int_distribution<int>(1, n - cur)(rng);
        cur = min(n, cur + step);
        path.push_back(cur);
    }
    // 现在path是单调递增到n的序列
    // 设置这些位置至少能跳到下一个位置
    for (size_t i = 0; i + 1 < path.size(); ++i) {
        int pos = path[i];
        int nxt = path[i+1];
        int max_jump = n - pos;
        // 确保a[pos]至少能跳到nxt
        if (a[pos] == 0) a[pos] = nxt - pos;
        else a[pos] = max(a[pos], nxt - pos);
    }
    // 对其他位置随机填充，但要保证不超过n-i
    for (int i = 1; i <= n; ++i) {
        if (a[i] == 0) {
            int max_jump = n - i;
            a[i] = uniform_int_distribution<int>(0, max_jump)(rng);
        } else {
            // 已经设置过，但可能超过最大限制？不会，因为nxt-pos <= n-pos
            a[i] = min(a[i], n - i);
        }
    }
    // 确保初始有解（理论上已有）
    assert(can_reach(a));
    return a;
}

// 生成一个链状（唯一路径）的数组
vector<int> generate_chain(int n) {
    vector<int> a(n+1);
    for (int i = 1; i < n; ++i) a[i] = 1;
    a[n] = 0;
    return a;
}

// 生成一个星形（1直接跳到所有，然后需要修改很多）
vector<int> generate_star(int n) {
    vector<int> a(n+1);
    a[1] = n - 1;
    for (int i = 2; i <= n; ++i) a[i] = 0;
    return a;
}

// 生成一个二叉树跳转（类似树形DP）
vector<int> generate_tree_like(int n, mt19937& rng) {
    // 构造一个DAG：每个点可以跳到后面若干点，但为了有唯一路径，需要修改。
    // 这里随便生成，但保证有路径
    return generate_random(n, rng);
}

int main() {
    auto seed = chrono::steady_clock::now().time_since_epoch().count();
    mt19937 rng(seed);
    const int TOTAL_FILES = 100;
    const int MAX_SUM_N = 3000; // 每个文件总n不超过3000

    for (int file = 1; file <= TOTAL_FILES; ++file) {
        // 决定本文件测试用例个数t (1~500, 但总n有限)
        int remaining_n = MAX_SUM_N;
        vector<int> ns;
        // 随机生成t，每个n至少2
        while (remaining_n >= 2) {
            int max_t = min(500, remaining_n / 2);
            if (max_t == 0) break;
            int t = uniform_int_distribution<int>(1, max_t)(rng);
            // 分配每个n
            int sum_n = 0;
            for (int i = 0; i < t; ++i) {
                int max_n = min(remaining_n - sum_n - (t - i - 1) * 2, 3000);
                if (max_n < 2) max_n = 2;
                int n = uniform_int_distribution<int>(2, max_n)(rng);
                ns.push_back(n);
                sum_n += n;
                if (sum_n > remaining_n) break;
            }
            if (sum_n <= remaining_n) {
                remaining_n -= sum_n;
                break;
            } else {
                ns.clear();
                // 重新分配
                continue;
            }
        }
        int t = ns.size();
        // 生成测试用例
        string filename = "data" + to_string(file) + ".in";
        ofstream fout(filename);
        if (!fout) {
            cerr << "无法创建文件 " << filename << endl;
            return 1;
        }
        fout << t << "\n";
        for (int idx = 0; idx < t; ++idx) {
            int n = ns[idx];
            // 随机选择生成类型
            int type = uniform_int_distribution<int>(0, 2)(rng);
            vector<int> a;
            if (type == 0) a = generate_chain(n);
            else if (type == 1) a = generate_star(n);
            else a = generate_random(n, rng);
            fout << n << "\n";
            for (int i = 1; i <= n; ++i) {
                fout << a[i] << (i == n ? "\n" : " ");
            }
        }
        fout.close();
        cout << "生成 " << filename << " : t=" << t << ", 总n=" << accumulate(ns.begin(), ns.end(), 0) << endl;
    }
    cout << "所有100个文件生成完毕！" << endl;
    return 0;
}