在昨日下午 14:00~18:00 举办的 LGR-208 中,我作为 T5 的出题人,为了防止选手利用评测交互库漏洞获取分数,采用了“下发与最终交互库不同的 checker.cpp 作为本地测试用具”的方式。以下为 checker.cpp 的源码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <utility>
#include <vector>//这个是 windows 下没问题,linux 下不加这个 CE,我一开始以为 UB 所以又下发了添加这行的版本
using namespace std;
const int N = 1e5 + 5;
int T;
int n[6], k[6];
vector<pair<int, int> > g[6];
int gcd(int x, int y) {
return (y == 0) ? x : gcd(y, x % y);
}
int unsol[6];
int main() {
freopen("restore.in", "r", stdin);
cin >> T;
for(int ti = 1; ti <= T; ti++) {
cin >> n[ti] >> k[ti];
int x, y;
for(int i = 1; i <= n[ti]; i++) cin >> x >> y, g[ti].push_back((pair<int, int>){x, y});
}
fclose(stdin);
freopen("restore.out", "r", stdin);
string str;
for(int ti = 1; ti <= T; ti++) {
cin >> str;
if(str == "No") unsol[ti] = 1;
else {
int x;
int gd = 0;
for(int i = 0; i < n[ti]; i++) {
cin >> x;
if(x < g[ti][i].first || x > g[ti][i].second) {
printf("Wrong answer on case %d.", ti);
return 0;
}
gd = gcd(x, gd);
}
if(gd < k[ti]) {
printf("Wrong answer on case %d, expect gcd >= %d, output = %d.", ti, k[ti], gd);
return 0;
}
}
}
fclose(stdin);
freopen("restore.ans", "r", stdin);
for(int ti = 1; ti <= T; ti++) {
cin >> str;
if(str == "Yes" && unsol[ti]) {
printf("Wrong answer on case %d.", ti);
return 0;
}
if(str == "Yes") {
int x;
for(int i = 1; i <= n[ti]; i++) cin >> x;
}
}
printf("Well done!");
return 0;
}
约在下午 16 时许,当时比赛已经进行到一半,开始有大量选手反映,checker.cpp 在本地无法正常使用,后来一位选手提供了新的 checker 才能比赛正常进行(其实不下发 checker 比赛也能进行,但选手调试很费劲),
所以问题是,为什么 checker.cpp 的初始版本在本机甚至学校机房的不同系统电脑下均可正常运行,而在部分选手电脑上运行失败?fclose(stdin); 作为程序读取多个文件的初始化方法是否具有普遍的可行性?如果不可行在什么时候不可行或者什么不严谨的用法导致不可行?
求解答,因为这个原因(算是很大一部分原因吧),这场比赛已经被批评了。