攀拓(PAT)- 程序设计(乙级)2024年夏季考试仿真卷答案

B-1 数字命理计算器

    西方人也讲数字命理,把人名对应到 11 个数字上,不同数字对应不同命运。这个数字集合包括 1 到 9、以及两个特殊的数字 11 和 22。
    他们把名字里每个英文字母按序号(1~26)循环对应 1~9(例如 a 对应 1,i 对应 9,j 对应 1,r 对应 9,s 对应 1,等等),然后加起来。如果这个和不是命理数字集合里的数,就把这个数的各位数字相加,如此反复直到得到一个命理数。
本题就请你实现这个计算器。

输入格式:

    输入第一行给出不超过 10 的正整数 n,随后 n 行,每行给出一个人名。每个人名由英文大小写字母和空格组成,至少有 1 个英文字母,一共不超过 100 个字符。

输出格式:

    对每个人名,在对应的一行中输出其命理数。

输入样例:

4
Alan Turing
Pythagoras
Von Neumann
John Fox

输出样例:

9
4
7
11

AC代码:

    change函数用于更新sum不符合要求(即不符合sum≥1 && sum ≤ 9 || sum == 11 || sum == 22)的值。使用getline函数确保录入一整行字符串。之后就是判断当前的字符的“命理数”,记得对9取模之后加1。

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

int change(int num);

int main()
{
	int n;
	cin >> n;
	getchar();
	for(int i = 0; i < n; i++)
	{
		string name;
		getline(cin, name);
		int sum = 0;
		for(int j = 0; j < name.length(); j++)
		{
			if(name[j] >= 'a' && name[j] <= 'z'){
				sum += ((name[j] - 'a') % 9 + 1);
			}else if(name[j] >= 'A' && name[j] <= 'Z'){
				sum += ((name[j] - 'A') % 9 + 1);
			}
		}
		while((sum < 1 || sum > 9) && sum != 11 && sum != 22){
			sum = change(sum);
		}
		cout << sum << endl;
	}
	return 0;
}

int change(int num)
{
	int sum = 0;
	while(num != 0){
		sum += (num % 10);
		num /= 10;
	}
	return sum;
}

B-2 这也行

输入格式:

    输入首先在第一行给出一个正整数 n(≤10),随后给出 n 个 2×2 矩阵的元素。每个矩阵分 2 行给出,每行有 2 个小于 10 的正整数。

输出格式:

    对每个输入的矩阵,在一行中输出判断的结果:如果满足题面要求则输出 1,否则输出 0。

输入样例:

3
2 3
6 9
1 2
3 4
3 4
6 8

输出样例:

1
0
1

AC代码:

    根据条件找准a、b、c、d直接进行if判断即可。

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

int main()
{
	int n;
	cin >> n;
	for(int i = 0; i < n; i++)
	{
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		if(a * a + b * c == a *10 + a && a * b + b * d == b * 10 + b && c * a + d * c == c * 10 + c && c * b + d * d == d * 10 + d){
			cout << 1 << endl;
		}else{
			cout << 0 << endl;
		}
	}
	return 0;
}

B-3 有多少零

    给定 n 个正整数,请你数数它们的乘积的末尾有多少个零。例如 26、225、48 的乘积是 280800,末尾有 2 个零。

输入格式:

    输入给出一个不超过 106 的正整数 n,下一行给出 n 个不超过 106 的正整数。

输出格式:

    在一行中输出给定的 n 个正整数的乘积末尾零的个数。

输入样例:

17
10 18 11 12 14 3 4 5 6 13 7 8 9 15 16 2 17

输出样例:

3

AC代码:

    因为10是由5和2构成的,计算乘积末尾有多少0,就是需要统计每一个乘积的因子中包含多少2和5,最后求2和5较小的个数,这样就是最多能够构成2 * 5 = 10也就是末尾0的个数。

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

int main()
{
	int n;
	cin >> n;
	int mod5 = 0;
	int mod2 = 0;
	for(int i = 0; i < n; i++)
	{
		int num;
		cin >> num;
		while(num % 5 == 0){
			mod5++;
			num /= 5;
		}
		while(num % 2 == 0){
			mod2++;
			num /= 2;
		}
	}
	cout << min(mod5, mod2);
	return 0;
}

B-4 换位与质因数

    给定一个正整数 n,任选其十进制表示中某两位不同的数字交换位置,得到另一个整数 m。问 m 的质因数集合与 n 的质因数集合有多大交集?
    例如 n=623457198 时,我们可以算出其质因数集合为 A = {2, 3, 7, 13, 380621}。如果将 2 和 9 交换得到 m=693457128,其质因数集合为 B = {2, 3, 7, 13, 109, 971}。则 A 和 B 的交集为 {2, 3, 7, 13},有 4 个因子。

输入格式:

    输入在一行中给出一个正整数 n(10<n≤109)。题目保证 n 至少有 2 个位置上的数字不相等。

输出格式:

    将 n 的任意两位不同数字交换位置后得到数字 m,找到其质因数集合与 n 的质因数集合有最大交集的那个 m。在一行中输出交集中质因子的个数和 m,其间以 1 个空格分隔,行首尾不得有多余空格。如果这样的 m 不唯一,则输出数值最小者。

输入样例:

623457198

输出样例:

4 123457698

样例解释:

    交集最大有 4 个因子的 m 有两个。除了题面中给出的数字外,还可以交换 6 和 1,得到的 123457698 的质因数集合为 {2, 3, 7, 13, 23, 29, 113},交集也是 {2, 3, 7, 13},且这个数字比 693457128 小,故输出。

AC代码:

    首先初始化足够多素数放入vector集合中,然后录入n,用flag数组将n的质因数保存起来,将质因数存在的索引的值设置为1,不存在的保留初始化的0,方便后续判断。而后利用to_string()方法将n转换为字符串,利用swap函数交换位置,判断得到的数和n不相等,然后从vector集合中找出其对应的质因数,如果当前的质因数个数大于当前的maxValue值或当前的质因数个数等于当前的maxValue值且当前数小于maxNum值都对maxValue和maxNum进行修改,每次换位之前记得将字符串进行复位,最后打印输出即可。

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

vector<int> prime;
int flag[1000005] = {0};

int isPrime(int n);

void Init()
{
	for(int i = 2; i <= 1000000; i++){
		if(isPrime(i)){
			prime.push_back(i);
		}
	}
}

int main()
{
	int n;
	cin >> n;
	Init();
	for(int i = 0; i < prime.size(); i++){
		if(n % prime[i] == 0){
			flag[prime[i]] = 1;
		}
	}
	string num = to_string(n);
	int maxValue = 0;
	int maxNum = 1000000001;
	for(int i = 0; i < num.length(); i++)
	{
		for(int j = i + 1; j < num.length(); j++)
		{
			swap(num[i], num[j]);
			int temp = stoi(num);
			if(temp == n){
				continue;
			}
			int cnt = 0;
			for(int k = 0; k < prime.size(); k++){
				if(flag[prime[k]] == 1 && temp % prime[k] == 0){
					cnt++;
				}
			}
			if(cnt > maxValue || (cnt == maxValue && temp < maxNum)){
				maxValue = cnt;
				maxNum = temp;
			}
			num = to_string(n);
		}
	}
	cout << maxValue << " " << maxNum << endl;
	return 0;
}

int isPrime(int n)
{
	if(n == 0 || n == 1)
		return 0;
	for(int i = 2; i <= sqrt(n); i++){
		if(n % i == 0)
			return 0;
	}
	return 1;
}

B-5 程序员找失主

    上图是一位捡到包的程序员给失主留的纸条,用了非常妙的双向加密:“在楼下捡了一个包,请失主看到了联系我!号码:1832834xxxx”,并注明前两个“xx”是“你身份证号第8-9位”,后面一个“x”是“你身份证号第五位”,最后一个“x”是“你身份证上最后一位”。
    给定这位程序员的完整手机号码,以及一大群人的身份证号,请你找出那位失主。

输入格式:

    输入首先在第一行给出程序员的 11 位数手机号码。第二行给出正整数 n(≤105),随后 n 行,每行给出一个 18 位身份证号。出于隐私保护,身份证号并不是真的,仅保证每个输入的号码都是 18 位,并且全部由数字组成。

输出格式:

    在一行中输出失主的身份证号。题目保证输出唯一。

输入样例:

18328349823
10
130124198703030914
412901197609212008
450703198308160035
412928194606180028
413921194910290412
240902197104212813
371521198711123153
140113196511250117
622922200306127013
342520198912300017

输出样例:

371521198711123153

AC代码:

    只需要判断后四位,利用stringstream对字符串拼接并判断,判断成功直接输出并结束程序即可。

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

int main()
{
	string phone;
	cin >> phone;
	int n;
	cin >> n;
	stringstream res;
	for(int i = phone.length() - 4; i < phone.length(); i++){
		res << phone[i];
	}
	for(int i = 0; i < n; i++)
	{
		string id;
		cin >> id;
		stringstream ss;
		ss << id[7];
		ss << id[8];
		ss << id[4];
		ss << id[id.length() - 1];
		if(ss.str() == res.str()){
			cout << id;
			break;
		}
	}
	return 0;
}
  • 11
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值