2026 校内联赛 第一轮题解(三年级)
2026-05-25 06:55:36
发布于:浙江
2026 年宋诏桥小学 C++ 联赛第一轮完整题解(三年级)
原帖发布于洛谷,故附件下载需要登录洛谷。
题解作者:hetao4025037
该比赛于 2026 年 3 月 23 日 12:00 正式开始,至 2026 年 3 月 23 日 13:00 完全结束(总时长 1 小时)。该比赛共 4 题,单题总分均为 100 分,共 400 分。
0. 作者声明
本人非比赛参赛选手,题目顺序由三年级第一名选手(shimuyang1024)提供,题解公开于洛谷。若有侵权,请告知(洛谷私信)删除。
1. 题目目录
提示:点击题目名称,可跳转到对应题目。
T4 B2067 药房管理
2. 题目详解
T1:B2008 计算 (a+b)×c 的值
本题极为入门,不作详细解释,只需要注意一点:
C++ 中的乘号(),需要使用 *。
本题无需考虑数据超出 int 类型的问题,因为输出最大也只会达到 。
完整代码(AC 代码):
#include <iostream>
using namespace std;
int main() {
int a, b, c;
cin >> a >> b >> c;
cout << (a + b) * c;
return 0;
}
T2:B2060 满足条件的数累加
题目大意
统计 范围内 的倍数之和。
解题思路 & 完整代码
我们可以定义一个变量:
-
ans:计数器 / 答案变量,存储范围 内,所有 的倍数的累加和。方法一:
使用暴力循环 ,每次判断该数是否为 的倍数,存入答案变量。
for循环写法:
for (int i = m; i <= n; i++)
循环体内的代码:
if (i % 17 == 0) ans += i;
完整代码(AC 代码):
#include <iostream>
using namespace std;
int main() {
int m, n, ans = 0;
cin >> m >> n;
for (int i = m; i <= n; i++)
if (i % 17 == 0) ans += i;
cout << ans;
return 0;
}
方法二:
通过 方法一 的分析,不难发现,方法一 的代码过于暴力,要遍历 次,还需要大量的判断,特别耗时!对此,我们可以进行优化。
我们都知道:相邻的 的倍数之间的差值都是 。根据这个特性,我们可以把 for 循环的 i++ 改为 i += 17。但是我们不能保证循环变量的起始值(上述代码中为 )是 的倍数,我们必须把循环变量的起始值改为 大于等于 最小的 的倍数(下文用 表示)。
可以使用 公式法 / 线性查找 的方法来获取。
公式法
(能被 整除的数可统一写成:, 为正整数。)
要求 ,变形得
满足不等式的最小整数 为对 向上取整
因此最小倍数
注意:C++ 自身的整数除法操作为向下取整
(1) 使用向上取整转向下取整的数学结论(不会的自行上网“补课”哦)
代入数据,可得
转为 C++ 代码:
int k = (m + 16) / 17 * 17;
(2) double 类型配合 <cmath> 库中的 ceil() 函数
接上文公式,我们可以用 m / 17.0 来取到小数值,再配合上 ceil() 函数:
int k = 17 * ceil(m / 17.0);
线性查找
从 开始(包括 ),依次向后检查,直到这个数是 的倍数(即找到目标数 ),这个循环最多会执行 次。
核心代码:
int k;
for (k = m; k < m + 17; k++) // k 最多会遍历到 m + 16 的位置(条件“k < m + 17”可省略)
if (k % 17 == 0) break;
完整代码(AC 代码):
#include <iostream>
#include <cmath> // 若选择 线性查找 方法可省略
using namespace std;
int main() {
int m, n, ans = 0;
cin >> m >> n;
/*
自行填充:求 k 代码(上述核心代码中任选一种填充)
*/
for (int i = k; i <= n; i += 17)
{
ans += i;
}
cout << ans;
return 0;
}
方法三:
方法二 与 方法一 相比,已经快了不少。
但代码还能继续优化吗?
答案是肯定的!
延续 方法二 的思路, 范围内所有 的倍数可以构成一个等差数列!
根据等差数列求和公式(不会的自行上网“补课”哦)
可知,我们还缺两个关键的值:末项 & 项数
末项求解 【不超过 的最大的 的倍数(下文用 表示)】
(能被 整除的数可统一写成:, 为正整数。)
要求 ,变形得
满足不等式的最大整数 为对 向下取整
因此最大倍数
注意:C++ 自身的整数除法操作为向下取整,与 中的向下取整完全一致!
直接转为 C++ 代码:
int b = n / 17 * 17;
项数求解(下文用 代替)
设首项为 ,末项为 ,公差为 ,项数记作 。
数列通项关系:
式子变形推导:
均为 的倍数,差值可整除,对应代码:
int t = (b - k) / 17 + 1;
最终求和公式
完整代码(AC 代码):
#include <iostream>
#include <cmath>
using namespace std;
int main() {
int m, n;
cin >> m >> n;
int k = (m + 16) / 17 * 17;
int b = n / 17 * 17;
int t = (b - k) / 17 + 1;
int ans = (k + b) * t / 2;
cout << ans;
return 0;
}
三种方法对比
| 对比维度 | 方法一 | 方法二 | 方法三 |
|---|---|---|---|
| 核心思路 | 遍历区间全数,判断倍数累加 | 定位首项,步长 遍历倍数累加 | 等差数列公式直接求值 |
| 时间复杂度 | |||
| 空间复杂度 | |||
| 代码难度 | 简单易懂 | 轻量数学推导 | 需数学推导 |
| 本题推荐度 | ★★★☆☆ | ★★★★★ | ★★★★☆ |
| 备注 | / | 时间复杂度省略 求 的代码 | / |
T3:B2044 有一门课不及格的学生
题目大意
已知一名学生的语文、数学、英语三科成绩,判断这个学生是不是三科中恰好有一门学科不及格()。
解题思路 & 完整代码
本题有较多方法求解,本文将取用其中两种较常用方法进行讲解。
我们首先定义一个变量:
cnt:计数器,存储不及格科目的数量。
方法一:
每次输入后,进行判断:是否不及格()。如果不及格,就累加 (cnt++;):
cin >> a;
if (a < 60) cnt++;
cin >> b;
if (b < 60) cnt++;
cin >> c;
if (c < 60) cnt++;
最后判断 cnt 是否正好为 1:
if (cnt == 1) cout << 1;
else cout << 0;
完整代码(AC 代码):
#include <iostream>
using namespace std;
int main() {
int a, b, c, cnt = 0;
cin >> a;
if (a < 60) cnt++;
cin >> b;
if (b < 60) cnt++;
cin >> c;
if (c < 60) cnt++;
if (cnt == 1) cout << 1;
else cout << 0;
return 0;
}
方法二:
根据 bool 类型转 int 类型的特性:
true->1false->0
我们不难发现,它正好符合上文中要求:如果不及格,就累加 (引出:如果及格,就累加 )。
这里的 正好就是 bool 类型转 int 类型的数值。
我们就可以把代码改成:
cin >> a;
cnt += a < 60;
cin >> b;
cnt += b < 60;
cin >> c;
cnt += c < 60;
完整代码(AC 代码):
#include <iostream>
using namespace std;
int main() {
int a, b, c, cnt = 0;
cin >> a;
cnt += a < 60;
cin >> b;
cnt += b < 60;
cin >> c;
cnt += c < 60;
if (cnt == 1) cout << 1;
else cout << 0;
return 0;
}
两种方法对比
| 对比维度 | 方法一 | 方法二 |
|---|---|---|
| 核心思路 | 分支判断统计不及格科目数 | 布尔运算隐式计数累加 |
| 时间复杂度 | ||
| 空间复杂度 | ||
| 代码难度 | 简单易懂 | 简洁精炼 |
| 本题推荐度 | ★★★★☆ | ★★★★★ |
T4:B2067 药房管理
题目大意
给定初始药量 与取药人数 ,依次接收每位病人取药量。药量充足则扣除对应数量,不足则判定取药失败,统计并输出失败总人数。
解题思路 & 完整代码
本题可以采用模拟法来解决。
我们可以定义两个变量:
ans:计数器 / 答案变量,存储没取到药的人数。
首先,循环处理 位病人的取药请求:
- 若病人需要的数量 当前库存:扣除药品,取药成功。
- 若病人需要的数量 当前库存:无法取药,失败人数 (
ans++;)。
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
if (x <= m) m -= x;
else ans++;
}
最后输出没取到药的总人数。
完整代码(AC 代码)
#include <iostream>
using namespace std;
int main() {
int m, n, ans = 0;
cin >> m >> n;
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
if (x <= m) m -= x;
else ans++;
}
cout << ans;
return 0;
}
3. 比赛总结
本次比赛整体难度较低,内容较为基础。
个人主观难度评价:★☆☆☆☆
*附
PDF 附件:
2026 年 宋诏桥小学 C++ 联赛第一轮完整题解(三年级).pdf(PDF 版题解不包含附件 & 附链接)
这里空空如也
















有帮助,赞一个