3231 字
16 分钟
GESP 2023年C++二级编程题解析

202312-1 小杨做题#

题目描述

为了准备考试,小杨每天都要做题。第 11 天,小杨做了 aa 道题;第 22 天,小杨做了 bb 道题;从第 33 天起,小杨每天做的题目数量是前两天的总和。

此外,小杨还规定,当自己某一天做了大于或等于 mm 题时,接下来的所有日子里,他就再也不做题了。

请问,到了第 NN 天,小杨总共做了多少题呢?

输入格式

总共 44 行。第一行一个整数 aa,第二行一个整数 bb,第三行一个整数 mm,第四行一个整数 NN

保证 0a,b100 \le a,b \le 10a,b<M<1,000,000a,b<M<1,000,0003N3643 \le N \le 364

输出格式

一行一个整数,表示小杨 NN 天里总共做了多少题目。

样例输入 1

1
2
10
5

样例输出 1

19

样例输入 2

1
1
5
8

样例输出 2

12

提示

【样例解释 1】

小杨第一天做 11 题,第二天做 22 题,第三天做 1+2=31+2=3 题,第四天做 2+3=52+3=5 题,第五天做 3+5=83+5=8 题。因此他总共做了 1+2+3+5+8=191+2+3+5+8=19 题。

【样例解释 2】

小杨前 55 天分别做了 1,1,2,3,51,1,2,3,5 题,由于第 55 天小杨做了 55 题,而 m=5m=5,于是小杨从此以后不再做题。因此小杨总共做了 1+1+2+3+5=121+1+2+3+5=12 题。

代码解析

注:已经学过数组或函数的同学可以使用数组递推或者递归函数

使用逐个递推的思想,每天的答题数量等于前两天之和,那么我们需要一个变量 n 来保存这一天答题的数量,然后将 b 赋值给 a, 将 n 赋值给 b,这样的话我们下一天就可以继续使用 a + b 来算出当天答题的数量

#include<iostream>
using namespace std;
int main() {
int a, b, m, N, n, sum;
cin >> a >> b >> m >> N;
// 记得加上第一天第二天的答题数量
sum = a + b;
// 一共 N 天,第1,2天的已经加了,从3开始
for (int i = 3; i <= N; i++) {
n = a + b;
a = b;
b = n;
sum += n;
if (n >= m)
break;
}
cout << sum;
return 0;
}

202312-2 小杨的H字矩阵#

题目描述

小杨想要构造一个 N×NN \times N 的 H 字矩阵(NN 为奇数),具体来说,这个矩阵共有 NN 行,每行 NN 个字符,其中最左列、最右列都是 | ,而中间一行(即第N+12\frac{N+1}{2}行)的第 2N12 \sim N-1 个字符都是 - ,其余所有字符都是半角小写字母 a。例如,一个 N=5N=5 的 H 字矩阵如下:

|aaa|
|aaa|
|---|
|aaa|
|aaa|

请你帮小杨根据给定的 NN 打印出对应的“H 字矩阵”。

输入格式

一行一个整数 NN5N495\le N \le 49 ,保证 NN 为奇数)。

输出格式

输出对应的“H 字矩阵”。

请严格按格式要求输出,不要擅自添加任何空格、标点、空行等任何符号。你应该恰好输出 NN 行,每行除了换行符外恰好包含 NN 个字符,这些字符要么是 - ,要么是 | ,要么是 a 。你的输出必须和标准答案完全一致才能得分,请在提交前仔细检查。

样例输入 1

5

样例输出 1

|aaa|
|aaa|
|---|
|aaa|
|aaa|

样例输入 2

7

样例输出 2

|aaaaa|
|aaaaa|
|aaaaa|
|-----|
|aaaaa|
|aaaaa|
|aaaaa|

代码解析

观察输出 '-', 'a', '|' 的坐标规律即可,题目中有给出中间一行的坐标计算方式 (第N+12\frac{N+1}{2}行)

#include<iostream>
using namespace std;
int main() {
int N;
cin >> N;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (j == 1 || j == N)
cout << '|';
else if (i == (N+1)/2)
cout << '-';
else
cout << 'a';
}
cout << endl;
}
return 0;
}

202309-1 小杨的 X 字矩阵#

题目描述

小杨想要构造一个 的 X 字矩阵( 为奇数),这个矩阵的两条对角线都是半角加号 + ,其余都是半角减号 - 。例如,一个 5×55 \times 5 的 X 字矩阵如下:

+---+
-+-+-
--+--
-+-+-
+---+

请你帮小杨根据给定的 打印出对应的“X 字矩阵”。

输入格式

一行一个整数 ( 5N495 \le N \le 49,保证为奇数)。

输出格式

输出对应的“X 字矩阵”。

请严格按格式要求输出,不要擅自添加任何空格、标点、空行等任何符号。你应该恰好输出 NN 行,每行除了换行符外恰好包含 NN 个字符,这些字符要么是 +,要么是 -

样例输入 1

5

样例输出 1

+---+
-+-+-
--+--
-+-+-
+---+

样例输入 2

7

样例输出 2

+-----+
-+---+-
--+-+--
---+---
--+-+--
-+---+-
+-----+

代码解析

主对角线和副对角线需要输出 '+',其余为 '-'

主对角线:i == j,副对角线 i+j == n-1

#include<iostream>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i == j || i + j == n-1)
cout << '+';
else
cout << '-';
}
cout << endl;
}
return 0;
}

202309-2 数字黑洞#

题目描述

给定一个三位数,要求各位不能相同。例如,352352 是符合要求的,112112 是不符合要求的。将这个三位数的三个数字重新排列,得到的最大的数,减去得到的最小的数,形成一个新的三位数。对这个新的三位数可以重复上述过程。神奇的是,最终一定会得到 495495

试试看,重新排列 352352,得到的最大数为 532532,最小数为 235235,它们的差是 297297;变换 297297,得到 972279=693972-279=693;变换 693693963369=594963-369=594;变换 594594954459=495954-459=495。因此,经过 44 次变换得到了 495495

现在,输入的三位数,你能通过编程得出,这个三位数经过多少次变换能够得到 495495 吗?

输入格式

输入一行,包含一个符合要求的三位数 NN

输出格式

输出一行,包含一个整数 CC,表示经过 CC 次变换得到 495495

样例输入 1

352

样例输出 1

4

代码解析

  1. 使用三位数的数位剥离方法得到 a, b, c,将 a, b, c 从小到大排序
  2. a, b, c 组合的大数减去组合的小数

N 不等于 495 的时候重复执行以上 1 2 过程,过程中使用 cnt 计数

#include<iostream>
using namespace std;
int main() {
int N, a, b, c, cnt = 0, sum = 0;
cin >> N;
while(N != 495) {
a = N % 10;
b = N / 10 % 10;
c = N / 100;
if (a > b) swap(a, b);
if (a > c) swap(a, c);
if (b > c) swap(b, c);
N = (c*100 + b*10 + a) - (a*100 + b*10 + c);
cnt++;
}
cout << cnt;
return 0;
}

202306-1 找素数#

题目描述

小明刚刚学习了素数的概念:如果一个大于 11 的正整数,除了 11 和它自身外,不能被其他正整数整除,则这个正整数是素数。现在,小明想找到两个正整数 AABB 之间(包括 AABB)有多少个素数。

输入格式

输入只有一行两个正整数 A,BA, B。约定 2AB10002 \le A \le B \le 1000

输出格式

输出一行,包含一个整数 CC,表示找到 CC 个素数。

样例输入 1

2
10

样例输出 1

4

提示

221010 之间有 44 个素数,分别为:22335577

代码解析

使用 for 循环从 a 开始到 b 结束枚举,挨个判断并计数

#include<iostream>
#include<cmath>
using namespace std;
int main() {
int a, b, cnt = 0;
cin >> a >> b;
for (int i = a; i <= b; i++) {
bool flag = true;
for (int j = 2; j*j <= i; j++)
if (i % j == 0)
flag = false;
if (flag)
cnt++;
}
cout << cnt;
return 0;
}

202306-2 自幂数判断#

题目描述

自幂数是指,一个 NN 位数,满足各位数字 NN 次方之和是本身。例如,15315333 位数,其每位数的 33 次方之和,13+53+33=1531^3+5^3+3^3=153,因此 153153 是自幂数;1634163444 位数,其每位数的 44 次方之和,14+64+34+44=16341^4+6^4+3^4+4^4=1634,因此 16341634 是自幂数。

现在,输入若干个正整数,请判断它们是否是自幂数。

输入格式

输入第一行是一个正整数 MM,表示有 MM 个待判断的正整数。约定 1M1001 \le M \le 100

从第 22 行开始的 MM 行,每行一个待判断的正整数。约定这些正整数均小于 10810^8

输出格式

输出 MM 行,如果对应的待判断正整数为自幂数,则输出英文大写字母 T\texttt T,否则输出英文大写字母 F\texttt F

提示:不需要等到所有输入结束在依次输出,可以输入一个数就判断一个数并输出,再输入下一个数。

样例输入 1

3
152
111
153

样例输出 1

F
F
T

样例输入 2

5
8208
548834
88593477
12345
5432

样例输出 2

T
T
T
F
F

代码解析

每输入一个数,需要做以下几件事:

  1. 判断这个数是几位数(n 位)
  2. 循环 n 次,不断求每一位的 n 次方
#include<iostream>
using namespace std;
int main() {
// N 为题目中的 N 个数
// x 是每一个需要判断的数字
// n 代表 x 是个 n 位数
// sum_n 用来计算每个 x 每一位数的 n 次方
// sum 用来统计每个 x 每一位数的 n 次方之和
int N, x, n, xx, sum_n, sum;
cin >> N;
for (int i = 0; i < N; i++) {
cin >> x;
n = 0;
sum = 0;
// 将 x 的值保存到 xx 里面
// 使用 while 统计 x 的位数 n
xx = x;
while (xx != 0) {
n++;
xx /= 10;
}
xx = x;
// 循环 n 次,计算每一位数的 n 次方之和
for (int j = 0; j < n; j++) {
sum_n = 1;
// 循环 n 次,计算每一位数的 n 次方
for (int k = 0; k < n; k++)
sum_n *= xx % 10;
xx /= 10;
sum += sum_n;
}
if (sum == x)
cout << 'T' << endl;
else
cout << 'F' << endl;
}
return 0;
}

202303-1 画三角形#

题目描述

输入一个正整数 nn,请使用大写字母拼成一个这样的三角形图案(参考样例输入输出):三角形图案的第 11 行有 11 个字母,第 22 行有 22 个字母,以此类推;在三角形图案中,由上至下、由左至右依次由大写字母 AZ\texttt{A}-\texttt{Z} 填充,每次使用大写字母 Z\texttt Z 填充后,将从头使用大写字母 A\texttt A 填充。

输入格式

输入一行,包含一个正整数 nn。约定 2n402 \le n \le 40

输出格式

输出符合要求的三角形图案。注意每行三角形图案的右侧不要有多余的空格。

样例输入 1

3

样例输出 1

A
BC
DEF

样例输入 2

7

样例输出 2

A
BC
DEF
GHIJ
KLMNO
PQRSTU
VWXYZAB

代码解析

单独定义 char 变量,每次打印后加一,超出 'Z' 重新变回 'A'

#include<iostream>
using namespace std;
int main() {
char c = 'A';
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
cout << c++;
if (c > 'Z')
c = 'A';
}
cout << endl;
}
return 0;
}

202303-2 百鸡问题#

题目描述

“百鸡问题”是出自我国古代《张丘建算经》的著名数学问题。大意为:

“每只公鸡 55 元,每只母鸡 33 元,每 33 只小鸡 11 元;现在有 100100 元,买了 100100 只鸡,共有多少种方案?”

小明很喜欢这个故事,他决定对这个问题进行扩展,并使用编程解决:如果每只公鸡 xx 元,每只母鸡 yy 元,每 zz 只小鸡 11 元;现在有 nn 元,买了 mm 只鸡,共有多少种方案?

输入格式

输入一行,包含五个整数,分别为问题描述中的 xxyyzznnmm。约定 1x,y,z101 \le x,y,z \le 101n,m10001 \le n,m \le 1000

输出格式

输出一行,包含一个整数 CC,表示有 CC 种方案。

样例输入 1

5 3 3 100 100

样例输出 1

4

样例输入 2

1 1 1 100 100

样例输出 2

5151

提示

【样例 1 解释】

这就是问题描述中的“百鸡问题”。44 种方案分别为:

  • 公鸡 00 只、母鸡 2525 只、小鸡 7575 只。
  • 公鸡 44 只、母鸡 1818 只、小鸡 7878 只。
  • 公鸡 88 只、母鸡 1111 只、小鸡 8181 只。
  • 公鸡 1212 只、母鸡 44 只、小鸡 8484 只。

代码解析

枚举法,假设公鸡的数量为 i,母鸡的数量为 j 进行枚举,小鸡 k 的数量可以通过 m - i - j 得到,根据题意所花的钱是整数,所以 k 必须是 z 的倍数,验证三种鸡的价钱只和是否等于 n 即可。

注意排除掉 k < 0 的情况。

这道题也可以写三层嵌套,k 的取值从 z 开始,每次 k += z

#include<iostream>
using namespace std;
int main() {
int x, y, z, n, m, cnt = 0;
cin >> x >> y >> z >> n >> m;
for (int i = 0; i <= n/x; i++) {
for (int j = 0; j <= n/y; j++) {
int k = m - i - j;
if (k >= 0 && k % z == 0 && i*x + j*y + k/z == n)
cnt++;
}
}
cout << cnt;
return 0;
}
GESP 2023年C++二级编程题解析
https://yezi.press/posts/gesp/gesp-cpp2-2023/
作者
Yezi 叶子
发布于
2023/12/01
许可协议
CC BY-NC-SA 4.0