【笔记】对拍
通过生成大量数据,比较不同代码的输出结果检验程序正确性。
数据生成器
使用 mt19937 梅森旋转算法,传入纳秒级别的种子,生成较强的随机数,然后在值域内取模。
#include<iostream>
#include<cstdio>
#include<random>
#include<chrono>
using namespace std;
int n;
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
int Rd(int l,int r){
return (rnd()%(r-l+1))+l;
}
int main(){
n=Rd(1,1000);
printf("%d\n",n);
for(int i=1;i<=n;i++){
printf("%d ",Rd(1,10000));
}
return 0;
}
随机数头文件:random 和 chrono。
如要在负数区间随机,正数取负即可。
比较器
使用 system 函数调用系统控制台命令,> 和 < 为重定向读写,与 cin cout 方向相反。fc 比较两个文件,如果没有差异返回 0,否则返回非 0。
#include<bits/stdc++.h>
using namespace std;
int main(){
for(int i=1;i<=10000;i++){
printf("Running on Test #%d\n",i);
system("data.exe > a.in");
system("baoli.exe < a.in > a.ans");
system("zhengjie.exe");
if(system("fc a.ans a.out")){
printf("Wrong Answer\n");
return 0;
}
}
printf("Accepted\n");
return 0;
}
正解可以不写重定向输入输出,检查 freopen。
检查器
对于一些 Special Judge 题目,我们可能需要手写检验输出结果是否合法的 checker。
可以单独新建一个文件存储 “Correct”,然后像上面一样把输出文件输入到 checker 中,如果合法就输出 “Correct” 之后 fc 比较两个字符串文件。
特殊数据生成
随机图
每条边随机两个点即可,如果有需要用 map 判一下重边。
随机树
方法一,对于每个节点,连到此前随机一个节点上,即添加边 \((i,\operatorname{rand}(1,i-1))\)。期望树高为 \(\log n\)。
方法二,对于每条边,随即两个节点 \(x,y\),用并查集判断连通性,如果连通则继续随机直到不连通。期望树高为 \(\sqrt n\)。
随机连通图
随机一棵树后,往树上加边。
随机 DAG
随机一个 \(1\sim n\) 的排列当作拓扑序,然后每条边都从小拓扑序连到大。
随机排列可以定义 \(a_i=i\),然后用 shuffle 函数洗牌。
shuffle(a+1,a+1+n,rnd);
在 algorithm 头文件中。
随机仙人掌
仙人掌为一些环排列在类似一棵树上,每个边只出现在一个环里的图。
可以先随机一棵树,然后随机从一个点开始往上跳,使其有 \(p\) 的概率成功,\(1-p\) 的概率失败,在失败处与起跳节点连边成环。
跳过的点除了失败处不能再被随机到。
环的个数和 \(p\) 都可以按需求调。
随机合法括号序列
先随机排列 \(n\) 个左括号和 \(n\) 个右括号。
然后我们规定左括号 \(+1\) 右括号 \(-1\),由此可以在 \(1\rightarrow 2n\) 的数轴上画出折线图。
在折线图的最低点处断开,把后面一段拼到前面即可。

浙公网安备 33010602011771号