PAT乙级19年秋冬考试题目整理


陆续做了两套练手,准备明天的考试,这里整理了几题个人感觉有价值的题目

2019年秋季考试

7-3 缘分数 (20分)

所谓缘分数是指这样一对正整数 a 和 b,其中 a 和它的小弟 a−1 的立方差正好是另一个整数 c 的平方,而 c 正好是 b 和它的小弟 b−1 的平方和。例如 8​3 − 7​3 = 169 = 13​2,而 13 = 3​2 ​+ 2​2,于是 8 和 3 就是一对缘分数。
给定 a 所在的区间 [m,n],是否存在缘分数?

输入格式:
输入给出区间的两个端点 0<m<n≤25000,其间以空格分隔。

输出格式:
按照 a 从小到大的顺序,每行输出一对缘分数,数字间以空格分隔。如果无解,则输出 No Solution。

输入样例 1:
8 200
输出样例 1:
8 3
105 10
输入样例 2:
9 100
输出样例 2:
No Solution

思路:这题有两个难点

  1. 怎么判断两数之差正好是另一个数的平方
  2. 怎么判断c是 b 和它的小弟 b−1 的平方和

判断两数之差正好是另一个数的平方。这里我用double类型d来存储一个数a的平方根,将这个d强制转换为整型,如果和转换前的d相等则说明这个数a有整数平方根;
怎么判断c是 b 和它的小弟 b−1 的平方和。两个相邻的数的平方和等于另一个数c,可以得出这两个相邻的数一定都小于等于c的平方根(如果其中一个大于c的平方根,则两数的平方和一定比c大)
这里为了优化时间我采用了双指针写法, 让i从1往后遍历,j从数c的平方根处往前遍历:

long long haveyf(long long n)
{
	for (long long i = 1, j = sqrt((double)n) + 1; i != j;)
	{
		if (i * i + j * j == n && j - i == 1) //平方和等于n且相差1说明满足条件,返回大的数即j
			return j;
		else if (i * i + j * j > n) //如果比n大,则j往前走一个,让平方和减小
			j--;
		else if (i * i + j * j < n) //如果比n小,则i往后走一个,让平方增大
			i++;
		else{ //如果平方和等于n,但是不相邻,则两个都往里靠
			j--;
			i++;
		}
	}
	return -1;
}

完整代码:

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
long long haveyf(long long);
int main()
{
	long long m, n, flag = 0;
	cin >> m >> n;
	for (long long i = m; i <= n; i++)
	{
		long long k = i - 1;
		double num = i * i * i - k * k * k;
		double d = sqrt(num);
		if ((long long)d == d) //是整数
		{
			long long p = haveyf(d);
			if (p != -1)
			{
				flag = 1;
				cout << i << ' ' << p << endl;
			}
		}
	}
	if (!flag)
		cout << "No Solution\n";
	system("pause");
	return 0;
}
long long haveyf(long long n)
{
	for (long long i = 1, j = sqrt((double)n) + 1; i != j;)
	{
		if (i * i + j * j == n && j - i == 1)
			return j;
		else if (i * i + j * j > n)
			j--;
		else if (i * i + j * j < n)
			i++;
		else{
			j--;
			i++;
		}
	}
	return -1;
}

7-5 链表合并 (25分)

给定两个单链表 L​1= a1→a​2→⋯→a​n−1→an和 L2=b1→b​2→⋯→bm−1→bm。如果 n≥2m,你的任务是将比较短的那个链表逆序,然后将之并入比较长的那个链表,得到一个形如 a1→a2→b​m→a3→a4→bm−1⋯ 的结果。例如给定两个链表分别为 6→7 和 1→2→3→4→5,你应该输出 1→2→7→3→4→6→5。

输入格式:
输入首先在第一行中给出两个链表 L1和 L2的头结点的地址,以及正整数 N (≤10​5),即给定的结点总数。一个结点的地址是一个 5 位数的非负整数,空地址 NULL 用 -1 表示。
随后 N 行,每行按以下格式给出一个结点的信息:
Address Data Next
其中 Address 是结点的地址,Data 是不超过 10​5的正整数,Next 是下一个结点的地址。题目保证没有空链表,并且较长的链表至少是较短链表的两倍长。

输出格式:
按顺序输出结果链表,每个结点占一行,格式与输入相同。

输入样例:
00100 01000 7
02233 2 34891
00100 6 00001
34891 3 10086
01000 1 02233
00033 5 -1
10086 4 00033
00001 7 -1
输出样例:
01000 1 02233
02233 2 00001
00001 7 34891
34891 3 10086
10086 4 00100
00100 6 00033
00033 5 -1

#include <iostream>
#include <vector>
#include <map>
using namespace std;
struct node
{
	int address;
	int val;
	int next;
};
vector<node> vec;
vector<node> vec1;
vector<node> vec2;
void insert();
int main()
{
	int head1, head2, n;
	cin >> head1 >> head2 >> n;
	map<int, node> mp;
	for (int i = 0; i < n; i++)
	{
		node s;
		cin >> s.address >> s.val >> s.next;
		mp[s.address] = s;
	}
	int address1 = head1;
	while (address1 != -1)
	{
		vec1.push_back(mp[address1]);
		address1 = mp[address1].next;
	}
	int address2 = head2;
	while (address2 != -1)
	{
		vec2.push_back(mp[address2]);
		address2 = mp[address2].next;
	}
	insert();
	for (int i = 0; i < vec.size() - 1; i++)
		printf("%05d %d %05d\n", vec[i].address, vec[i].val, vec[i].next);
	printf("%05d %d %d\n", vec[vec.size() - 1].address, vec[vec.size() - 1].val, vec[vec.size() - 1].next);
	system("pause");
	return 0;
}
void insert()
{
	int cnt = 0, i = 0, j = 0;
	if (vec1.size() >= vec2.size() * 2)
	{
		reverse(vec2.begin(), vec2.end());
		for (i = 0, j = 0; j < vec2.size() && i < vec1.size();)
		{
			if (cnt == 2)
			{
				cnt = 0;
				vec.push_back(vec2[j++]);
				continue;
			}else
			{
				cnt++;
				vec.push_back(vec1[i++]);
			}
		}
		if (i < vec1.size())
			for (; i < vec1.size(); i++)
				vec.push_back(vec1[i]);
		if (j < vec2.size())
			for (; j < vec2.size(); j++)
				vec.push_back(vec2[j]);
	}
	else if (vec2.size() >= vec1.size() * 2)
	{
		reverse(vec1.begin(), vec1.end());
		for (i = 0, j = 0; j < vec1.size() && i < vec2.size();)
		{
			if (cnt == 2)
			{
				cnt = 0;
				vec.push_back(vec1[j++]);
				continue;
			}else
			{
				cnt++;
				vec.push_back(vec2[i++]);
			}
		}
		if (i < vec2.size())
			for (; i < vec2.size(); i++)
				vec.push_back(vec2[i]);
		if (j < vec1.size())
			for (; j < vec1.size(); j++)
				vec.push_back(vec1[j]);
	}
	for (int k = 0; k < vec.size() - 1; k++)
		vec[k].next = vec[k + 1].address;
	vec[vec.size() - 1].next = -1;
}

2019年冬季考试

7-4 擅长C (20分)

当你被面试官要求用 C 写一个“Hello World”时,有本事像下图显示的那样写一个出来吗?
输入格式:
输入首先给出 26 个英文大写字母 A-Z,每个字母用一个 7×5 的、由 C 和 . 组成的矩阵构成。最后在一行中给出一个句子,以回车结束。句子是由若干个单词(每个包含不超过 10 个连续的大写英文字母)组成的,单词间以任何非大写英文字母分隔。
题目保证至少给出一个单词。
输出格式:
对每个单词,将其每个字母用矩阵形式在一行中输出,字母间有一列空格分隔。单词的首尾不得有多余空格。
相邻的两个单词间必须有一空行分隔。输出的首尾不得有多余空行。
输入样例:

..C..
.C.C.
C...C
CCCCC
C...C
C...C
C...C
CCCC.
C...C
C...C
CCCC.
C...C
C...C
CCCC.
.CCC.
C...C
C....
C....
C....
C...C
.CCC.
CCCC.
C...C
C...C
C...C
C...C
C...C
CCCC.
CCCCC
C....
C....
CCCC.
C....
C....
CCCCC
CCCCC
C....
C....
CCCC.
C....
C....
C....
CCCC.
C...C
C....
C.CCC
C...C
C...C
CCCC.
C...C
C...C
C...C
CCCCC
C...C
C...C
C...C
CCCCC
..C..
..C..
..C..
..C..
..C..
CCCCC
CCCCC
....C
....C
....C
....C
C...C
.CCC.
C...C
C..C.
C.C..
CC...
C.C..
C..C.
C...C
C....
C....
C....
C....
C....
C....
CCCCC
C...C
C...C
CC.CC
C.C.C
C...C
C...C
C...C
C...C
C...C
CC..C
C.C.C
C..CC
C...C
C...C
.CCC.
C...C
C...C
C...C
C...C
C...C
.CCC.
CCCC.
C...C
C...C
CCCC.
C....
C....
C....
.CCC.
C...C
C...C
C...C
C.C.C
C..CC
.CCC.
CCCC.
C...C
CCCC.
CC...
C.C..
C..C.
C...C
.CCC.
C...C
C....
.CCC.
....C
C...C
.CCC.
CCCCC
..C..
..C..
..C..
..C..
..C..
..C..
C...C
C...C
C...C
C...C
C...C
C...C
.CCC.
C...C
C...C
C...C
C...C
C...C
.C.C.
..C..
C...C
C...C
C...C
C.C.C
CC.CC
C...C
C...C
C...C
C...C
.C.C.
..C..
.C.C.
C...C
C...C
C...C
C...C
.C.C.
..C..
..C..
..C..
..C..
CCCCC
....C
...C.
..C..
.C...
C....
CCCCC
HELLO~WORLD!

输出样例:

C...C CCCCC C.... C.... .CCC.
C...C C.... C.... C.... C...C
C...C C.... C.... C.... C...C
CCCCC CCCC. C.... C.... C...C
C...C C.... C.... C.... C...C
C...C C.... C.... C.... C...C
C...C CCCCC CCCCC CCCCC .CCC.

C...C .CCC. CCCC. C.... CCCC.
C...C C...C C...C C.... C...C
C...C C...C CCCC. C.... C...C
C.C.C C...C CC... C.... C...C
CC.CC C...C C.C.. C.... C...C
C...C C...C C..C. C.... C...C
C...C .CCC. C...C CCCCC CCCC.
#include <iostream>
#include <vector>
#include <map>
using namespace std;
struct node
{
	char c[7][5];
};
int main()
{
	map<char, node> mp;
	for (int i = 0; i < 26; i++)
	{
		node s;
		for (int j = 0; j < 7; j++)
		{
			for (int k = 0; k < 5; k++)
			{
				cin >> s.c[j][k];
			}
		}
		mp['A' + i] = s;
	}
	getchar();
	vector<string> str;
	string word, ans;
	getline(cin, word);
	int cnt = 0, flag = 0;
	for (int i = 0; i < word.size(); i++)
	{
		if (word[i] >= 'A' && word[i] <= 'Z')
			ans += word[i];
		else
		{
			str.push_back(ans);
			ans.clear();
		}
	}
	for (int i = 0; i < str.size(); i++)
	{
		for (int j = 0; j < 7; j++)
		{
			for (int k = 0; k < str[i].size(); k++)
			{
				for (int p = 0; p < 5; p++)
					cout << mp[str[i][k]].c[j][p];
				if (k != str[i].size() - 1)
					cout << ' ';
			}
			if (j != 6)
				cout << endl;
		}
		if (i != str.size() - 1)
			cout << endl << endl;
	}	
	return 0;
}

7-5 区块反转 (25分)

给定一个单链表 L,我们将每 K 个结点看成一个区块(链表最后若不足 K 个结点,也看成一个区块),请编写程序将 L 中所有区块的链接反转。例如:给定 L 为 1→2→3→4→5→6→7→8,K 为 3,则输出应该为 7→8→4→5→6→1→2→3。

输入格式:
每个输入包含 1 个测试用例。每个测试用例第 1 行给出第 1 个结点的地址、结点总个数正整数 N (≤105)、以及正整数 K (≤N),即区块的大小。结点的地址是 5 位非负整数,NULL 地址用 −1 表示。
接下来有 N 行,每行格式为:
Address Data Next
其中 Address 是结点地址,Data 是该结点保存的整数数据,Next 是下一结点的地址。
输出格式:
对每个测试用例,顺序输出反转后的链表,其上每个结点占一行,格式与输入相同。

输入样例:
00100 8 3
71120 7 88666
00000 4 99999
00100 1 12309
68237 6 71120
33218 3 00000
99999 5 68237
88666 8 -1
12309 2 33218
输出样例:
71120 7 88666
88666 8 00000
00000 4 99999
99999 5 68237
68237 6 00100
00100 1 12309
12309 2 33218
33218 3 -1

#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
struct node
{
	int address;
	int val;
	int next;
};
int main()
{
	int head, n, k;
	cin >> head >> n >> k;
	map<int, node> mp;
	for (int i = 0; i < n; i++)
	{
		node s;
		cin >> s.address >> s.val >> s.next;
		mp[s.address] = s;
	}
	vector<node> list;
	while (head != -1)
	{
		list.push_back(mp[head]);
		head = mp[head].next;
	}
	int cnt = 0, flag = 0;
	for (int i = 0; i < list.size(); i++)
	{
		if (k == list.size() || k == 0)
			break;
		else
		{
			if (flag && list.size() - i < k)
			{
				reverse(list.begin() + i, list.end());
				break;
			}
			if ((i + 1) % k == 0)
			{
				flag = 1;
				reverse(list.begin() + cnt, list.begin() + i + 1);
				cnt = i + 1;
			}
		}
	}
	if (k != list.size() && k != 0)
		reverse(list.begin(), list.end());
	for (int i = 0; i < list.size() - 1; i++)
		list[i].next = list[i + 1].address;
	list[list.size() - 1].next = -1;
	for (int i = 0; i < list.size() - 1; i++)
		printf("%05d %d %05d\n", list[i].address, list[i].val, list[i].next);
	printf("%05d %d %d\n", list[list.size() - 1].address, list[list.size() - 1].val, list[list.size() - 1].next);
	system("pause");
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值