关于 stdin 反复重定向
  • 板块学术版
  • 楼主船酱魔王
  • 当前回复3
  • 已保存回复6
  • 发布时间2024/11/24 10:08
  • 上次更新2024/11/24 11:47:00
查看原帖
关于 stdin 反复重定向
420998
船酱魔王楼主2024/11/24 10:08

在昨日下午 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); 作为程序读取多个文件的初始化方法是否具有普遍的可行性?如果不可行在什么时候不可行或者什么不严谨的用法导致不可行?

求解答,因为这个原因(算是很大一部分原因吧),这场比赛已经被批评了。

2024/11/24 10:08
加载中...