SCP-J 2026 重现赛

已结束 IOI 开始于: 2026-10-21 17:00 100 小时 主持人: 6

SCP-J 2026 重现赛

点我下载大样例

视频讲解


/*
========================================
          C++ 对拍程序使用说明
========================================

一、什么是对拍?

对拍是一种检查程序正确性的方法。

基本思路:
1. 编写一份自己需要检查的代码(std.cpp)。
2. 编写一份保证正确的暴力代码(brute.cpp)。
3. 随机生成大量测试数据。
4. 让两份程序运行相同的测试数据。
5. 比较两份程序的输出是否一致。

如果输出不一致,说明至少有一份程序存在问题,
此时输出对应的测试数据,方便定位错误。

----------------------------------------

二、使用前的准备工作

需要准备以下三个 C++ 文件:

1. std.cpp
   自己编写的待检查代码(通常是正解或优化算法)。

2. brute.cpp
   保证正确的暴力代码。
   暴力代码可以运行得慢一些,但必须保证结果正确。

3. check.cpp
   当前这个对拍程序,用来生成随机数据、
   运行两份程序并比较答案。

----------------------------------------

三、编译三个程序

在终端中执行:

g++ std.cpp -o std.exe
g++ brute.cpp -o brute.exe
g++ check.cpp -o check.exe

编译完成后,会生成三个可执行文件:

std.exe
brute.exe
check.exe

----------------------------------------

四、修改输入输出

由于本程序使用文件进行对拍,因此需要保证:

1. std.cpp 从 1.in 读取,向 std.out 输出。
2. brute.cpp 从 1.in 读取,向 brute.out 输出。

可以在两份程序的 main() 开头分别添加:

std.cpp:

freopen("1.in", "r", stdin);
freopen("std.out", "w", stdout);

brute.cpp:

freopen("1.in", "r", stdin);
freopen("brute.out", "w", stdout);

注意:两份程序读取的输入文件必须相同,
但输出文件必须不同。

----------------------------------------

五、修改随机数据生成器

根据题目的输入格式,修改 gen() 函数。

例如当前代码生成的数据格式为:

第一行:一个整数 n,范围为 [1, 10]。
第二行:n 个整数,每个整数范围为 [1, 10]。

如果题目的输入格式发生变化,
则需要修改 gen() 中的数据生成方式。

----------------------------------------

六、开始对拍

在终端运行:

.\check.exe

程序将不断执行:

生成随机数据
    ↓
运行 std.exe
    ↓
运行 brute.exe
    ↓
比较 std.out 和 brute.out
    ↓
答案相同:继续生成下一组数据
答案不同:输出出错的数据,停止对拍

找到错误后,可以直接查看 1.in 文件,
将其作为反例进行调试。

----------------------------------------

七、注意事项

1. 本程序适用于 Windows 系统。
   其中 fc /b 是 Windows 的文件比较命令。

2. 三个 exe 文件应放在同一个工作目录下。

3. 修改 std.cpp 或 brute.cpp 后,必须重新编译。

4. 暴力程序必须保证正确,否则对拍没有意义。

5. 当前程序比较的是输出文件的每个字节,
   因此空格、换行不同,也可能被判定为不一致。

6. 如果程序死循环或者运行时间过长,
   当前对拍程序不会自动终止超时进程。

========================================
*/

#include <bits/stdc++.h> // 引入 C++ 常用标准库
using namespace std;      // 使用标准命名空间

// 创建随机数生成器
// mt19937 是一种高质量的伪随机数生成器
// time(0) 使用当前时间作为随机种子,使每次运行生成的数据不同
mt19937 rnd(time(0));

// 生成一个范围在 [l, r] 内的随机整数(包含两端)
int f(int l, int r)
{
    // rnd() 生成一个随机数
    // % (r - l + 1) 将其限制在 [0, r-l]
    // 再加上 l,得到 [l, r] 内的随机整数
    return rnd() % (r - l + 1) + l;
}

// 随机数据生成函数
// 每调用一次,就生成一组新的测试数据
void gen()
{
    // 创建输出文件 1.in
    // 如果文件已经存在,会覆盖原来的内容
    ofstream out("1.in");

    // 随机生成一个 [1, 10] 的整数 n
    int n = f(1, 10);

    // 将 n 写入 1.in,并换行
    out << n << "\n";

    // 生成 n 个随机整数
    for (int i = 1; i <= n; i++)
    {
        // 随机生成一个 [1, 10] 的整数
        int a = f(1, 10);

        // 将随机数写入文件,用空格分隔
        out << a << " ";
    }

    // 最后输出一个换行
    out << "\n";

    // 函数结束后,out 自动关闭
    // 此时随机测试数据已经写入 1.in
}

int main()
{
    // 无限循环,不断生成数据并进行对拍
    // 直到找到两份程序输出不同的测试数据
    while (true)
    {
        // 生成一组新的随机测试数据,保存到 1.in
        gen();

        // 运行待检查程序 std.exe
        // std.exe 读取 1.in,结果写入 std.out
        system("std.exe");

        // 运行暴力程序 brute.exe
        // brute.exe 读取 1.in,结果写入 brute.out
        system("brute.exe");

        // 比较两个输出文件的内容
        // fc 是 Windows 下的文件比较命令
        // /b 表示按二进制逐字节比较
        // > nul 表示不显示比较命令的输出信息
        // 两个文件相同,返回值通常为 0
        // 两个文件不同,返回值非 0
        int res = system("fc /b std.out brute.out > nul");

        // 如果两份程序的输出不一致
        if (res != 0)
        {
            // 打开当前出错的测试数据文件
            ifstream in("1.in");

            // 将文件中的全部内容输出到控制台
            // rdbuf() 可以直接读取文件的整个缓冲区
            cout << in.rdbuf();

            // 找到反例,退出无限循环,停止对拍
            break;
        }

        // 如果输出一致,就继续下一轮循环
        // 再生成一组新数据进行测试
    }

    // 程序正常结束
    return 0;
}
状态
已结束
规则
IOI
题目
4
开始于
2026-10-21 17:00
结束于
2026-10-25 21:00
持续时间
100 小时
主持人
参赛人数
6