2025年7月6日全国青少年信息素养大赛C++编程初中组复赛真题+答案解析

2025年7月6日全国青少年信息素养大赛C++编程初中组复赛真题+答案解析

一、选择题

第1题 C++表达式 (5>3)*3 的值是()

A. 0
B. true
C. 1
D. 3

答案:D(值为3)
解析:

  1. 布尔表达式的结果:在C++中,5>3是一个布尔表达式,判断结果为“真”(true)。
  2. 布尔值与整数的转换:C++中,布尔值参与算术运算时会自动转换为整数——true转换为1false转换为0
  3. 计算过程(5>3)*3等价于true*3,进一步转换为1*3=3
  4. 结论:表达式结果为3,对应选项D。

第2题 以下说法错误的是?

int a, b;  
cin >> a >> b;  
a = a*b;  
b += a;  
cout << a << " " << b << endl; 

A. 输入 2 3,程序输出:6 9
B. 输入 1 1,程序输出:2 2
C. a = a * b 替换成 a *= b,效果一样
D. b += a 替换成 b = b + a,效果一样

答案: B

解析: 当输入 1 1 时,执行 a = 1*1 = 1b = 1 + 1 = 2,因此输出应为 1 2,而非 2 2


第3题 想输出 ‘a’~'z’26个字母,横线处填()

for(int i=1; i <=26; i++)  {
	cout << ____ << endl; 
}

A. char(‘a’ + i)
B. char(‘a’ - 1 + i)
C. ‘a’ - 1 + i
D. ‘a’ + i

答案: B

解析:i=1 时,'a' - 1 + i = 'a'i=26 时对应 'z'。通过 char() 强制转换为字符类型,确保输出字母而非ASCII码值。


第4题 以下说法错误的是()

int n;  
cin >> n;  
while(n>0)  
{  
    cout << n % 10;  
    n /=10;  
} 

A. 输入 345,输出 543
B. 输入 100,输出 001
C. 输入任意非负整数,程序能依次输出该数从个位到最高位的所有数位
D. 如果把 n /=10这一句删掉,运行程序并输入 123,程序会死循环

答案: C

解析: 0为非负整数,当输入为 0 时,n > 0 条件不成立,程序无输出,因此选项C中“任意非负整数”的描述错误。


第5题 运行程序并输入9,输出为()

#include<iostream>  
using namespace std;  
int a[15];  
int main()  
{  
    int n;  
    cin >> n;  
    a[1]=a[2]=1;  
    for(int i=3; i<=n; i++)  
    {  
        a[i] = a[i-1] + a[i-2];  
    }  
    cout << a[n];  
    return 0;  
} 

A.2
B.21
C.34
D.55

答案: C

解析: 程序实现斐波那契数列,输入 9 时计算得 a[9] = 34


二、编程题


第一题 探险装备采购

题目描述

探险队即将开启新的探险!出发之前,他们需要采购一些探险装备。探险队共有n人,每人需要3个探照灯、1 个氧气瓶,4 捆安全绳。已知探照灯x元一个,气瓶y元一个,安全绳z元一捆,请你写一个程序,帮助他们计算买探险装备总共需要花费多少钱。

输入描述

一行输入四个整数 n、x、y、z,分别表示探险队人数、探照灯单价、氧气瓶单价、安全绳单价,整数之间用空格隔开。

输出描述

一个整数,代表购买装备的总花费。

样例输入

40 3 5 4

样例输出

1200

样例说明

40 × (3×3 + 1×5 + 4×4) = 1200

数据范围

2 ≤ n,x,y,z ≤ 100

题目解析

需计算每人所需装备的总费用,再乘以人数得到总花费:

  1. 每人费用:3×x + 1×y + 4×z
  2. 总花费:n × (3x + y + 4z)
解题步骤
  1. 读取输入的 n、x、y、z
  2. 计算每人的装备费用:3*x + y + 4*z
  3. 总花费 = n × 每人费用
  4. 输出总花费。
代码实现
#include <iostream>
using namespace std;

int main() {
    // 输入探险队人数、探照灯单价、氧气瓶单价、安全绳单价
    int n, x, y, z;
    cin >> n >> x >> y >> z;
    
    // 计算总花费:每人需要3个探照灯、1个氧气瓶、4捆安全绳
    int total = n * (3 * x + y + 4 * z);
    
    // 输出总花费
    cout << total << endl;
    return 0;
}
知识点总结
  1. 算术运算:通过乘法和加法计算总费用;
  2. 输入输出:使用 cin 读取输入,cout 输出结果;
  3. 公式推导:将实际问题转化为数学公式(总花费 = 人数 × 每人费用)。

第二题 地形判断

题目描述

探险队勘探宝藏埋藏之地的地形,测量了东侧、中央、西侧三个关键点的海拔高度,需要编写程序,根据输入的三个点海拔高度判断地形,地形分类如下:

  • 1 山丘:中央高于东侧和西侧。
  • 2 谷地:中央低于东侧和西侧。
  • 3 平原:东侧、中央、西侧高度相同。
  • 4 东侧坡:西侧高于中央,中央高于东侧。
  • 5 西侧坡:东侧高于中央,中央高于西侧。
  • 6 普通地形:不属于以上五种的任意一种。

输出要求

  • 如果是山丘,输出 "hill"
  • 如果是谷地,输出 "valley"
  • 如果是平原,输出 "plain"
  • 如果是西侧坡,输出 "west"
  • 如果是普通地形,输出 "common"

输入描述

输入三个整数 a、b、c,用空格隔开,分别表示东侧、中央、西侧的海拔高度。

输出描述

输出一个字符串,为 "hill" "valley" "plain" "east" "west" "common" 中的一个。

样例输入

60 60 60

样例输出

plain

数据范围

1 ≤ a,b,c ≤ 1000

题目解析

通过条件判断区分地形类型:

  1. 山丘:b > a && b > c
  2. 谷地:b < a && b < c
  3. 平原:a == b && b == c
  4. 东侧坡:c > b && b > a
  5. 西侧坡:a > b && b > c
  6. 其他情况为普通地形。
解题步骤
  1. 读取输入的 a、b、c
  2. 通过 if-else 分支判断地形类型;
  3. 输出对应的地形字符串。
代码实现
#include <iostream>
using namespace std;

int main() {
    // 输入东侧、中央、西侧海拔
    int a, b, c;
    cin >> a >> b >> c;
    
    // 按条件判断地形
    if (b > a && b > c) {          // 山丘:中央高于东侧和西侧
        cout << "hill" << endl;
    } else if (b < a && b < c) {   // 谷地:中央低于东侧和西侧
        cout << "valley" << endl;
    } else if (a == b && b == c) { // 平原:三者高度相同
        cout << "plain" << endl;
    } else if (c > b && b > a) {   // 东侧坡:西侧>中央>东侧
        cout << "east" << endl;
    } else if (a > b && b > c) {   // 西侧坡:东侧>中央>西侧
        cout << "west" << endl;
    } else {                       // 普通地形
        cout << "common" << endl;
    }
    
    return 0;
}
知识点总结
  1. 多条件分支:使用 if-else 处理复杂条件判断;
  2. 逻辑运算:通过 &&(逻辑与)组合多个条件;
  3. 字符串输出:根据条件输出不同的字符串结果。

第三题 藏宝地宫探险

题目描述

探险队即将进入藏宝地宫。地宫由n个区域组成,编号1~n,探险队用高科技探明了每个区域的宝藏数量a₁,a₂,…,aₙ。同时,他们也发现有些区域隐藏着机关,n个区域的机关的伤害值用b₁,b₂,…,bₙ表示,如果编号为i的区域没有机关,则bᵢ=0。如果踏入了有机关的区域,不仅无法获得该区域的宝藏,还会受到相应的伤害值。

探险队准备了一个防御值为k的护盾抵挡伤害,如果探险队依次经过编号1~n区域的过程中受到的伤害总量超过了护盾的防御值k,则本次探险过于危险,输出“Danger”,结束探险。如果探险队依次经过编号1~n的全部区域受到的伤害总量没有超过护盾的防御值k,则输出获得的宝藏总数。

输入

第1行:两个空格隔开的正整数nk,表示区域个数和护盾防御值。
第2行:n个非负整数a₁,a₂,…,aₙaᵢ表示编号为i的区域的宝藏数量。
第3行:n个非负整数b₁,b₂,…,bₙbᵢ表示编号为i的区域的机关伤害值。

输出

一个整数表示获得的宝藏总数,或者一个字符串“Danger”

数据范围

1<=n<=1000,1<=k<=10000,0<=aᵢ,bᵢ<=100

输入样例1

5 6
4 1 9 4 2
0 3 0 1 2

输出样例1

13

输入样例2

4 3
3 7 2 1
0 2 2 0

输出样例2

Danger

题目解析

需模拟探险队经过每个区域的过程:

  1. 累加每个区域的伤害值,若超过k则输出“Danger”
  2. 若区域无机关(bᵢ=0),则累加宝藏数量;
  3. 遍历完所有区域后,输出宝藏总数。
解题步骤
  1. 读取输入的 n、k,以及宝藏数组 a 和伤害数组 b
  2. 遍历每个区域,累加伤害值和宝藏数量;
  3. 若伤害值超过 k,输出“Danger”并结束;
  4. 否则输出宝藏总数。
代码实现
#include <iostream>
using namespace std;

int main() {
    // 输入区域个数n和护盾防御值k
    int n, k;
    cin >> n >> k;
    
    // 输入宝藏数量数组和机关伤害数组
    int a[1005], b[1005];
    for (int i = 0; i < n; i++) cin >> a[i];
    for (int i = 0; i < n; i++) cin >> b[i];
    
    int harm = 0;  // 累计伤害值
    int treasure = 0;  // 累计宝藏数
    bool danger = false;  // 是否触发危险
    
    for (int i = 0; i < n; i++) {
        harm += b[i];  // 累加当前区域的伤害
        
        // 如果伤害超过护盾值,标记危险并退出循环
        if (harm > k) {
            danger = true;
            break;
        }
        
        // 无机关(伤害值为0)时,累加宝藏
        if (b[i] == 0) {
            treasure += a[i];
        }
    }
    
    // 输出结果
    if (danger) {
        cout << "Danger" << endl;
    } else {
        cout << treasure << endl;
    }
    
    return 0;
}
知识点总结
  1. 数组遍历:使用循环遍历宝藏和伤害数组;
  2. 条件判断:根据伤害值和机关状态决定是否累加宝藏;
  3. 状态标记:使用布尔变量标记是否触发危险。

第四题 回文书名统计

题目描述

古代王国的尚经阁里藏着许多奇怪的书籍,这些书籍的标题都是由小写字母组成的字符串。其中一些书籍比较特殊,书名是回文串(无论从左往右读还是从右往左读都一样)。这些特殊的书籍可能记录着上古的秘密。由于书籍太多,你需要写一个程序来统计回文书名的数量,并将所有回文书名按输入先后顺序连在一起输出。

输入

第一行,一个正整数n,表示共有n本书,
接下来n行,每行一个字符串,表示书名。每个字符串由小写字母组成,不包含空格。

输出

第一行输出一个整数,表示回文书名的个数。
第二行输出一个字符串,所有回文书名依次连在一起的结果,中间没有空格。如果不存在回文书名,则不输出。

数据范围

1<=n<=100,每个字符串长度不超过50。

输入样例

5
level
world
kayak
hello
civic

输出样例

3
levelkayakcivic

题目解析

需判断每个书名是否为回文串,并统计结果:

  1. 回文串判断:双指针法(从两端向中间比较字符);
  2. 统计回文串数量,并拼接结果。
解题步骤
  1. 读取输入的 n 和书名;
  2. 对每个书名,使用双指针法判断是否为回文串;
  3. 统计回文串数量,并拼接结果;
  4. 输出数量和拼接后的字符串。
代码实现
#include <iostream>
#include <string>
using namespace std;

// 判断字符串是否为回文
bool isPalindrome(string s) {
    int left = 0, right = s.size() - 1;
    while (left < right) {
        // 双指针从两端向中间比较
        if (s[left] != s[right]) return false;
        left++;
        right--;
    }
    return true;
}

int main() {
    int n;
    cin >> n;  // 输入书籍数量
    
    int cnt = 0;  // 回文书名数量
    string result;  // 回文书名拼接结果
    
    for (int i = 0; i < n; i++) {
        string s;
        cin >> s;  // 输入书名
        
        if (isPalindrome(s)) {  // 判断是否回文
            cnt++;
            result += s;  // 拼接回文书名
        }
    }
    
    // 输出结果
    cout << cnt << endl;
    if (cnt > 0) {
        cout << result << endl;
    }
    
    return 0;
}
知识点总结
  1. 回文串判断:双指针法高效判断字符串是否为回文;
  2. 字符串拼接:使用 += 操作拼接回文书名;
  3. 函数封装:将回文判断逻辑封装为函数,代码更清晰。

第五题 神秘地宫宝石

题目描述

探险队进入了一个神秘地宫,里面有 n 堆宝石,每堆宝石个数为正整数,旁边有一面石碑,上面刻着取宝石的规则:
探险者需要选定一堆宝石,从这堆宝石开始每隔 k 堆宝石拿一堆宝石,选准一堆宝石,选取的那堆会受到神秘力量的惩罚!

已知每一堆宝石的数量,请问探险队最多能拿走多少个宝石?

输入描述

第一行:两个正整数 n、k,用一个空格隔开;
第二行:n 个正整数 a₁, a₂, …, aₙ ,表示每堆宝石的个数。

输出描述

一个整数,表示最多能拿走的宝石个数。

样例 1
输入

7 2
4 6 2 1 10 1 3

输出

16

提示

【样例说明】
从第 1 堆宝石开始拿,拿走第 1、4、7 堆宝石,总数为 8
从第 2 堆宝石开始拿,拿走第 2、5 堆宝石,总数为 16
从第 3 堆宝石开始拿,拿走第 3、6 堆宝石,总数为 3
从第 4 堆宝石开始拿,拿走第 4、7 堆宝石,总数为 4
从第 5 堆宝石开始拿,拿走第 5 堆宝石,总数为 10
从第 6 堆宝石开始拿,拿走第 6 堆宝石,总数为 1
从第 7 堆宝石开始拿,拿走第 7 堆宝石,总数为 3

数据范围

60% 的数据:1 ≤ n ≤ 10³,1 ≤ k ≤ 10³,且 k 不超过 100
每堆宝石个数不超过 10⁵。
60% 数据:枚举 n 个位置,每 k 个选一个,求总分最大量,O(n²/k)
100% 数据:枚举前 k-1 个位置,O(n)

题目解析

需枚举所有可能的起始堆,计算每种起始堆能拿到的宝石总数,取最大值:

  1. 起始堆范围:前 k 堆(避免重复计算);
  2. 对于每个起始堆,每隔 k 堆取一次宝石(步长为 k+1);
  3. 累加宝石数量,更新最大值。
解题步骤
  1. 读取输入的 n、k 和宝石数组 a
  2. 枚举前 k 个起始堆(start 从 0 到 k);
  3. 对于每个起始堆,按步长 k+1 遍历数组,累加宝石数量;
  4. 更新最大宝石数量;
  5. 输出最大值。
代码实现
#include <iostream> 
using namespace std;

int main() {
    int n, k;
    // 读取输入的两个整数:
    // n 表示宝石堆数量
    // k 表示间隔的堆数(即每次跳过 k 个堆)
    cin >> n >> k;

    int a[1001];  // 定义数组 a[],用于存储每一堆宝石的数量,最多支持 1000 堆

    // 读取每一堆宝石的数量
    for (int i = 0; i < n; i++) {
        cin >> a[i];  // 输入第 i 堆的宝石数量,存入数组 a[]
    }

    int max_sum = 0;  // 记录所有方案中,最多能拿到的宝石总数,初始为 0

    // 遍历所有可能的起始点
    // 注意:我们只需要枚举前 k+1 个位置作为起始点(即下标 0 到 k)
    // 因为跳跃步长为 k+1,如果从更靠后的点开始,路径就会过短或重复
    for (int start = 0; start <= k && start < n; start++) {
        int sum = 0;  // 当前起点路径下能拿到的宝石数

        // 从当前起点出发,每次跳过 k 个堆,即步长为 k+1
        // 直到跳出数组范围
        for (int i = start; i < n; i += k + 1) {
            sum += a[i];  // 累加当前位置的宝石数
        }

        // 如果当前路径得到的宝石数比当前最大值大,更新最大值
        if (sum > max_sum) {
            max_sum = sum;
        }
    }

    // 输出最终得到的最多宝石总数
    cout << max_sum << endl;

    return 0;  // 程序正常结束
}
题目解析

核心逻辑是枚举所有可能的起始堆,计算每种情况下能拿到的宝石总数:

  • 从第 start 堆开始,每次间隔 k 堆(即步长为 k+1)选取宝石;
  • 由于步长固定,枚举前 k+1 个起始堆即可覆盖所有可能的路径(避免重复计算);
  • 累加每个路径的宝石数量,取最大值作为结果。
知识点总结
  1. 循环嵌套:外层循环枚举起始堆,内层循环按步长取宝石;
  2. 优化思想:通过限制起始堆范围(前 k+1 个)减少计算量;
  3. 最值求解:使用变量 max_sum 记录并更新最大宝石数量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值