LuoguP3692 夏幻的考试 题解

本蒟蒻甚至怀疑自己连个普及-的题目都做不出来了。。。然而还是做出来了


一道坑点多多的大模拟题目。

首先就是这道题目特有的cout<<endl的问题,不过本人亲测发现好像这道题目与\n在Windows和Linux的兼容性没有太大的关系,用\n也能过得去本题。

然后开始盘点这道题目所有的过程。

\(Step~1\):输入

输入\(T,n\)倒是没有问题的。

关键是之后输入正确答案以及考号,考卷类型和每题的填涂答案的情况。首先是输入正确答案,用一个字符数组保存,然后用scanf("%s", ...)读入就可以了(不过要注意下标!这个在AC代码里会有呈现)。

然后考号,直接定义一个大小为17的数组,然后用scanf("%1d", ...)读入。

接着是考卷类型,也用同样方法输入。

最后是答案填涂,同样方法输入不啰嗦。

\(Step~2\):处理数据

我们发现考号的范围在十进制下的1到10000。然而在这里输入的是二进制。怎么办呢?我们用电脑自带的计算器查一下,发现10000在二进制下是这样的:

我们发现它只有14位数。

所以,我们可以想到这样一个特判:只要在16位二进制的第1、2位中有数,这个考号就是不合法的。

那么一般情况怎么弄呢?

很简单,直接通过位运算得到其十进制即可。

比如说\((1000010000)_2=1*2^9+1*2^4=528\)

所以考号就这么处理完了。接下来判断就无需再讲了,一波if-else搞定。

然后是考卷类型。因为在题目中,0表示A卷,1表示B卷。所以,只要比对一下是否填涂且仅填涂了正确的考卷类型就行了。具体就是:如果根据考好得出是\(A\)卷,且试卷类型栏只填涂了\(A\)卷这个类型,就是\(Type~Correct\),或者得出是\(B\)卷,且试卷类型栏只填涂了\(B\)卷这个类型,也是\(Type~Correct\)。否则全部都是\(Type~Incorrect\)

最后是考试答案。我们用一种类似于康托展开的方式,将每个填涂数据转化为一种状态,比如我们发现\(1000\)对应的是\(A\)这个答案,所以将这个填涂情况转换成\(1000\)这个数。

\(Step~3\):解决问题

首先考号,按照上面的处理方法判断。

然后考卷类型也是如此。

最后是考试答案。注意,在本人的代码中,正解答案的题目下标是\(0,1,2,...,n-1\),然而考生答案的题目下标是\(1,2,3,...n\)。所以需要注意一一比对。还有,因为本题中,默认满分是\(100\)分,所以每题积分直接取平均值,最好用\(double\)存储(精度高些)。

其他就没啥好讲了。总的来说,这个题目真心是个纯模拟题目,不过很多细节。祝大家刷题愉快!

最后来贴上正解代码~

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>
#include <cmath>
using namespace std;

inline int read() {
	int f = 1, x = 0;
	char c = getchar();
	while(c < '0' || c > '9') {
		if(c == '-')	f = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') {
		x = x * 10 + c - '0';
		c = getchar();
	}
	return x * f;
}

int T, n;
double per;
char correct[57];
struct node {
	int id[17], A, B, ans[57][5], note[57];
}a[1007];

int main() {
	T = read(), n = read();
	per = 100.0 / (n * 1.0);
	scanf("%s\n", correct);
// 	printf("%.1lf\n", per);
	for(int i = 1; i <= T; ++i) {
		int flag = 0, sum = 0;
		for(int j = 1; j <= 16; ++j) {
			scanf("%1d", &a[i].id[j]);
			if((j == 1 || j == 2) && a[i].id[j])	flag = 1;
			else {
//				printf("%d ", 16 - j);
				sum += a[i].id[j] * (int)pow(2, 16 - j);
//				printf("%d\n", sum);
			}
		}
		if(sum < 1 || sum > 10000)	flag = 1;
		scanf("%1d%1d", &a[i].A, &a[i].B);
		for(int j = 1; j <= n; ++j)
			for(int k = 1; k <= 4; ++k) {
				scanf("%1d", &a[i].ans[j][k]);
				a[i].note[j] = a[i].note[j] * 10 + a[i].ans[j][k];
			}
		if(flag) {
			puts("Wrong ID\n");
			continue;
		}
		printf("ID: %d\n", sum);
		if((!a[i].id[16] && a[i].A && !a[i].B) || (a[i].id[16] && !a[i].A && a[i].B))
			puts("Type Correct");
		else
			puts("Type Incorrect");	
		flag = 0; double num = 0.0;
		for(int j = 1; j <= n; ++j) {
			flag = 0;
//			printf("%d %c\n", a[i].note[j], correct[j - 1]);
			if(a[i].note[j] == 1000 && correct[j - 1] == 'A')		num++;
			else if(a[i].note[j] == 100 && correct[j - 1] == 'B')	num++;
			else if(a[i].note[j] == 10 && correct[j - 1] == 'C')	num++;
			else if(a[i].note[j] == 1 && correct[j - 1] == 'D')		num++; 
		}
		num *= per;
		printf("%.1lf\n\n", num);
	}
	return 0;
}
posted @ 2021-12-23 21:13  Eason_AC  阅读(77)  评论(0)    收藏  举报