PAT(乙级)2022年冬季考试答案

B-1 谣言检测仪

谣言有很多种,本题请你设计一种检测仪,专门针对一类吹牛话术进行验证。

有人喜欢吹牛,说自己做一场报告有 N 次掌声。现给定这个人的报告录音文字版,其中如果有掌声,记录中会出现 (zhangsheng) 字样。请你统计一下报告过程中到底出现了多少次掌声,并且与其说出的掌声次数做个比较,来判断这是不是谣言。

输入格式:

输入在第一行给出一个不超过 100 的正整数 N,即某人号称自己收获的掌声次数。

随后给出由英文字母、数字、标点符号(包括 ,.;:!)、空格、回车、以及 (zhangsheng) 组成的报告文本,为不超过 105 个字符的非空字符串,其中语音记录的文本以 # 结尾。

输出格式:

首先输出语音记录中真实的掌声次数。如果真实次数不小于 N,则随后空 1 格输出 True;否则输出 False

输入样例 1:

3
Hello (zhangsheng).  Glad to meet everyone(zhangsheng).
See you (zhangsheng) next time.#

输出样例 1:

3 True

输入样例 2:

3
Hello (zhangsheng).  Glad to meet everyone(zhang
sheng). Let me hear your zhangsheng!
#

输出样例 2:

1 False

AC代码:

遍历字符串,对字符串进行检测即可。

#include "bits/stdc++.h"
using namespace std;

int main()
{
	int N;
	cin >> N;
	getchar();
	char c = getchar();
	stringstream ss;
	while(c != '#')
	{
		ss << c;
		c = getchar();
	}
	string s = ss.str();
	int cnt = 0;
	for(int i = 0; i < s.length(); i++)
	{
		if(i + 11 < s.length() && s[i] == '(' && s[i + 1] == 'z' && s[i + 2] == 'h' && s[i + 3] == 'a' && s[i + 4] == 'n' && s[i + 5] == 'g' && s[i + 6] == 's' && s[i + 7] == 'h' && s[i + 8] == 'e' && s[i + 9] == 'n' && s[i + 10] == 'g' && s[i + 11] == ')'){
			cnt++;
		}
	}
	cout << cnt << " ";
	if(cnt >= N){
		cout << "True";
	}else{
		cout << "False";
	}
	return 0;
}

B-2 一道数学题

设整数 m 和 n 在给定闭区间 [a,b] 内,且满足等式(n^2 + mn + m^2)^2  = 1。请你求出 m2+n2 的最大值。

输入格式:

输入给出两个正整数 a 和 b(1<a<b≤3×104),为闭区间的两个端点。

输出格式:

在一行中按照以下格式输出:

max( m^2 + n^2 ) = s

其中 s 是题面要求的 m^2 + n^2 的最大值,mn 分别对应能取到最大值的 m 和 n 的值。

输入样例:

10 100

输出样例:

max( 55^2 + 89^2 ) = 10946

AC代码:

根据题目等式条件直接编写程序即可。

#include "bits/stdc++.h"
using namespace std;

int main()
{
	int a, b;
	cin >> a >> b;
	int max = -1;
	int maxM = -1;
	int maxN = -1;
	for(int m = a; m <= b; m++)
	{
		for(int n = a; n <= b; n++)
		{
			if((n * n - m * n - m * m) * (n * n - m * n - m * m) == 1){
				int num = m * m + n * n;
				if(num > max){
					max = num;
					maxM = m;
					maxN = n;
				}
			}
		}
	}
	cout << "max( " << maxM << "^2 + " << maxN << "^2 ) = " << max;
	return 0;
}

B-3 代号大本钟

在“一年一度喜剧大赛”上有一部作品《代号大本钟》,讲的是二战期间德国情报站里有一位英国间谍,代号“大本钟”。当最后情报站只剩下两个人的时候,站长坚信真正的间谍不是间谍,然后用了一下排除法,那就只有他自己是大本钟了……

现在假设情报站进行了 N 人次排查,最后请你用排除法来查一下,谁是那个“大本钟”?

输入格式:

输入第一行给出一个正整数 N(≤10^4)。随后 N 行,按照排查的时间先后顺序,每行给出一人次排查的结果,格式为:

代号 排查结果

其中 代号 是一个 4 位数字,为被排查的人的编号;排查结果 为 1 表示这人有间谍嫌疑,为 0 表示排除了这人的嫌疑。注意:同一个人可能被排查多次,但无论此前有多少次被列为嫌疑人,本次排查结果为 0 就排除了前面的所有怀疑。

输出格式:

根据排除法,在一行中列出所有被排查的人中有可能是“大本钟”的人的编号。编号按递增序给出,相邻编号间以 1 个空格分隔,行首尾不得有多余空格。

如果只有一个人有嫌疑,则在第二行输出 Da Ben Zhong is found!;如果有多个嫌疑,则输出 There are n suspects.,其中 n 是嫌疑人的个数。

题目保证至少有一个人是“大本钟”。

输入样例 1:

10
1234 1
2234 0
3234 1
1234 1
3234 1
2234 0
2234 1
3234 0
1234 0
1234 0

输出样例 1:

2234
Da Ben Zhong is found!

输入样例 2:

10
1234 1
2234 0
3234 1
1234 1
3234 1
2234 0
2234 1
3234 0
1234 0
1234 1

输出样例 2:

1234 2234
There are 2 suspects.

AC代码:

通过map集合的键值对属性关系,如果当前没有嫌疑了,就使用erase方法擦除当前键值对即可。

#include "bits/stdc++.h"
using namespace std;

map<int, int> mp;

int main()
{
	int N;
	cin >> N;
	for(int i = 0; i < N; i++)
	{
		int id, res;
		cin >> id >> res;
		if(res == 1){
			mp[id] = 1;
		}else if(res == 0){
			if(mp.find(id) != mp.end()){
				mp.erase(id);
			}
		}
	}
	if(mp.size() == 1){
		map<int, int>::iterator it = mp.begin();
		printf("%04d\n", it->first);
		cout << "Da Ben Zhong is found!";
	}else if(mp.size() > 1){
		for(map<int, int>:: iterator it = mp.begin(); it != mp.end(); it++){
			if(it != mp.begin())	cout << " ";
			printf("%04d", it->first);
		}
		cout << "\nThere are " << mp.size() << " suspects.";
	}
	return 0;
}

B-4 真分数的约分

真分数是指分子小于分母的分数。对分数进行约分,是指将分子分母共同的因子消去。

但还有一种另类的简单约分:直接将分子分母共有的一对数字消去。这种方法大多数情况下都得不到正确的结果,但有时候却也碰巧能对!例如 26/65 = 2/5 就是直接消去 6 的结果。

现给定一个真分数,你的任务是判断它是否能用简单约分方法得到正确结果。注意:如果有多种简单约分的可能,一定按从左到右的顺序约掉数字。

输入格式:

输入在一行中给出一个真分数的分子 a 和分母 b,其间以空格分隔。题目保证 0<a<b≤10^5

输出格式:

在一行中先后输出这个真分数在简单约分前后的样子。如果两个分数相等,则在两者间加一个 = 号;否则加一个 != 号。格式为 a/b = c/da/b != c/d

输入样例 1:

39 195

输出样例 1:

39/195 = 3/15

输入样例 2:

1234 23452

输出样例 2:

1234/23452 != 1/52

输入样例 3:

1234 5678

输出样例 3:

1234/5678 = 1234/5678

AC代码:

一边使用辗转相除法快速得到最简分式并保存,另一边使用题目给出的约分方式从左向右进行约分,得到的式子相等则输出"=",否则输出"!="。

#include "bits/stdc++.h"
using namespace std;

int gcd(int a, int b);

int main()
{
	int a, b;
	cin >> a >> b;
	int num = gcd(a, b);
	string res = to_string(a / num) + '/' + to_string(b / num);
	string sA = to_string(a);
	string sB = to_string(b);
	for(int i = 0; i < sA.length() && sA.length() > 0 && sB.length() > 0; i++)
	{
		for(int j = 0; j < sB.length() && sA.length() > 0 && sB.length() > 0; j++)
		{
			if(sA[i] == sB[j]){
				sA.erase(i, 1);
				sB.erase(j, 1);
				i--;
				j--;
			}
		}
	}
	int rA, rB;
	if(sA.length() != 0 && sB.length() != 0){
		rA = stoi(sA);
		rB = stoi(sB);
	}else if(sA.length() == 0 && sB.length() != 0){
		rA = 0;
		rB = stoi(sB);
	}else if(sA.length() != 0 && sB.length() == 0){
		rA = stoi(sA);
		rB = 0;
	}else if(sA.length() == 0 && sB.length() == 0){
		rA = 0;
		rB = 0;
	}
	if(rA == 0 && rB == 0){
		cout << a << "/" << b << " != " << "0/0";
	}else{
		cout << a << "/" << b;
		int rnum = gcd(rA, rB);
		string r = to_string(rA / rnum) + '/' + to_string(rB / rnum);
		if(res == r){
			cout << " = ";
		}else{
			cout << " != ";
		}
		cout << rA << "/" << rB;
	}
	return 0;
}

int gcd(int a, int b)
{
	if(b == 0)
		return a;
	return gcd(b, a % b);
}

B-5 取行李

一般机场里,航班到达后,旅客们会去到达区的行李传送带那里取自己的行李。

现假设有一座特别的机场,每条传送带只有一个取行李的窗口。旅客们必须排好队,逐一到窗口取自己的行李。但是当某人到窗口前,发现行李不是自己的,那人就只好走到队尾去等下一次机会。此时那件行李会一直等在窗口,直到它的主人把它取走。假设每一次认领需要 1 分钟,本题就要求你计算传送带清空需要的时间、以及旅客们的平均等待时间。

例如,假设行李 i 属于旅客 i。行李的到达顺序是 1、2、3,旅客的到达顺序是 2、1、3。则 1 号行李要等 2 分钟才能被主人 1 号旅客取走。这时行李队列中有 2、3,旅客队列中是 3、2。于是 2 号行李还要等 2 分钟才能被 2 号旅客取走,最后 3 号在第 5 分钟取走行李。旅客们的平均等待时间是 (2+4+5)/3≈3.7。

输入格式:

输入首先在第一行给出一个正整数 N(≤103)。下一行给出 N 个数字,是 [1,N] 区间内整数的一个重排列,表示旅客队列。这里我们假设行李队列是按 1、2、……、N 有序的,并且行李 i 属于旅客 i。一行中数字间以空格分隔。

输出格式:

在一行中输出传送带清空需要的时间、以及旅客们的平均等待时间(输出小数点后 1 位)。数字间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:

5
3 5 1 2 4

输出样例:

9 6.0

题目引用自攀拓考试真题(2022年冬季)。

AC代码:

使用STL的deque容器进行计算判断旅客和行李是否匹配即可。

#include "bits/stdc++.h"
using namespace std;

deque<int> dq;

int main()
{
	int N;
	cin >> N;
	for(int i = 0; i < N; i++)
	{
		int people;
		cin >> people;
		dq.push_back(people);
	}
	int sumTime = 0;
	int Time = 0;
	int people = 0;
	for(int i = 1; i <= N; i++)
	{
		while(people != i){
			people = dq.front();
			Time++;
			dq.pop_front();
			if(people != i){
				dq.push_back(people);
			}else{
				break;
			}
		}
		sumTime += Time;
	}
	cout << Time << " ";
	printf("%.1lf", sumTime * 1.0 / N);
	return 0;
}
  • 10
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值