对拍是什么?对拍是一种校验程序正确性的方法,通过比较两个程序的同一个测试样例的输出结果,就可以做到判断正确性。

想必各位dalao们都会对拍吧,在oi这种shabi赛制中,对拍就显得尤为重要。

但是,如果你哪天运气不好,遇到了构造题,应该怎么办呢?

其实说的高大上,这个玩意其实不难,营养并不多,比赛的时候动动小聪明其实也能想到

构造题

构造题大多都是让你根据给你的条件,搞出一种符合条件的答案,所以答案可能不唯一。

我们对拍的时候就是不知道答案不唯一的问题,所以在这种情况下,我们可以在比较程序里手写check函数来判断就行了,下面我用一道题来举个例子。

CF743C

题目的意思就是说给你个nn,然后要求你构造出一组(x,y,z)(x,y,z)满足1x+1y+1z=2n\frac{1}{x}+\frac{1}{y}+\frac{1}{z}=\frac{2}{n}

懒得说解法了,说一说这题怎么对拍吧。

假如我们写了个这个代码想要检测对不对:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin >> n;
if (n == 1) {
cout << -1;
} else {
cout << n << ' ' << n + 1 << ' ' << n * (n + 1);
}
return 0;
}

我们可以在代码里搞一个随机数据生成器,然后再写一个check判断就ok了。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<bits/stdc++.h>
using namespace std;
tuple<int, int, int> solve(int n)
{
if (n == 1) {
return {-1, -1, -1};
} else {
return {n, n + 1, n * (n + 1)};
}
}
bool check(int tcc, tuple<int, int, int> a)
{
if (tcc == 1) {
return get<0>(a) == -1;
}
int ta = get<0>(a);
int tb = get<1>(a);
int tc = get<2>(a);
return (double)1 / (double)ta + (double)1 / (double)tb + (double)1 / (double)tc == (double)2 / (double)tcc;
}
int main()
{
srand(time(0));
while (1) {
int tc = rand();
if (check(tc, solve(tc))) {
cout << "ok!" << '\n';
} else {
cout << tc << '\n';
break;
}
}
return 0;
}

这个代码其实很简单就能看懂,本质上就是不断放进去tc然后判断答案是否合法,碰到了构造题大部分都可以用这个思路来检测。