第9章 一级必背编程模板(编程题通关)

第9章 一级必背编程模板(编程题通关)

关于本章

本章把 GESP C++ 一级(2023–2025 全部公开机试真题 + 2026 高频押题)按题型归纳成 12 个必背代码模板。每个模板都给出可直接提交的完整程序(C++17、4 空格缩进、关键行带注释),配上大白话讲解和易错警告。背熟这 12 个模板,一级编程题(2 道 ×25 分 = 50 分)基本稳过。

评测透明说明

本工作区未安装 C++ 编译器(已确认无 g++/clang++/cl),所有代码为人工逐行核对 + 手算样例验证,未在机子上真实编译运行。请用 Dev-C++ 5.11(GESP 官方指定环境) 实地编译自测后再放心背。真题来源已在各模板标注(博客园 kkman2000 汇总、ACGO 题单、ACGO 2026 押题)。

一级编程题五大类思维导图


9.1 一级编程题套路总览

一级编程题逻辑直来直去,按考点只分五类(见上图):

类别出现频率代表真题(洛谷/B 编号)
① 基础计算与整除★★★★★长方形面积 B3850、小杨买书 B3952、温度转换 B4062、图书馆里的老鼠 B4257
② 时间日期换算★★★★当天的第几秒 B3847、休息时间 B4033、小杨的考试 B3921
③ 数字性质判断★★★找因数 B3953、立方数 B4034、美丽数字 B4035、闰年求和 B3846
④ 循环累加求和★★★★累计相加 B3862、金字塔 B4047、小明的幸运数 B3902
⑤ 条件逻辑与最值★★★商店折扣 B4046、假期阅读 B4044、小杨的爱心快递 B4445
一级铁律
  • 所有输入 n ≤ 10000,暴力枚举完全可行,不用想高级算法(O(n²) 也能过)。
  • 语法结构是固定的三件套:输入 cin/scanf → 处理(分支/循环)→ 输出 cout/printf。
  • 一级不考数组、字符串、函数、指针,所以下面模板全部用最基础写法,方便你硬背。

9.2 模板 1:标准程序骨架(趁手模板)

每道题都从这套骨架开始,只改中间“处理部分”。

#include <iostream>
using namespace std;

int main() {
// 1. 定义变量
// 2. 读入:cin >> a >> b;
// 3. 处理:计算 / 分支 / 循环
// 4. 输出:cout << ans << endl;
return 0;
}
// 用 scanf / printf 的等价写法(一级两者都接受)
#include <cstdio>

int main() {
int a, b;
scanf("%d %d", &a, &b); // 注意变量前加 &
printf("%d\n", a + b);
return 0;
}
骨架易错点
  • 漏写 using namespace std;(用 cin/cout 时必须写)。
  • scanf 读入时变量前一定要加 &,否则编译/运行出错。
  • main 函数最后的 return 0; 一级不扣分,但写上更稳。

9.3 模板 2:求最大 / 最小值(三数比大小)

真题:小杨的爱心快递 B4445(多条件分支 + 取最小值)、值日 B4045。

#include <iostream>
using namespace std;

int main() {
int a, b, c;
cin >> a >> b >> c;
int m = a; // 先假设 a 最大
if (b > m) m = b; // 谁更大就更新 m
if (c > m) m = c;
cout << m << endl; // m 就是最大值
return 0;
}
大白话

“打擂台法”:先让 a 当擂主,后面每个数来挑战,比擂主大就上位。最小值把 > 改成 < 即可。

易错

求最大值初始值要设成“很小”(如第一个数);求最小值初始值要设成“很大”(如第一个数),别把 m 初始化成 0 再去求最小值(会出错)。


9.4 模板 3:整除与取余(小杨买书类)

真题:小杨买书 B3952(书 13 元,零花钱 m,求最多买几本 + 剩多少)、小杨购物 B4034(成对买 A、B)、图书馆里的老鼠 B4257。

#include <iostream>
using namespace std;

int main() {
int m; // 零花钱
cin >> m;
cout << m / 13 << endl; // 整除:最多买几本
cout << m % 13 << endl; // 取余:剩下多少钱
return 0;
}

成对购买(小杨购物):A 单价 a、B 单价 b,钱 n,求能买几对:

#include <iostream>
using namespace std;

int main() {
int a, b, n;
cin >> a >> b >> n;
cout << n / (a + b) << endl; // 一对的成本是 a+b
return 0;
}
整除 vs 浮点(一级最常错!)

5 / 2 = 2(整数除法,直接砍掉小数),不是 2.5!
需要小数结果时必须写成 5.0 / 2 或 5 / 2.0。买书/找零这类题本来就是整数,用 / 和 % 才对。


9.5 模板 4:闰年判断(分支经典)

真题:闰年求和 B3846(样题,闰年判断 + 循环累加)。

#include <iostream>
using namespace std;

int main() {
int y;
cin >> y;
// 闰年:能被4整除且不能被100整除,或能被400整除
if ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0))
cout << "yes" << endl;
else
cout << "no" << endl;
return 0;
}
大白话

两个条件“或”起来:① 普通闰年(4 的倍数但不是 100 的倍数);② 世纪闰年(400 的倍数,如 2000 年是闰年,1900 年不是)。


9.6 模板 5:时间换算(统一为秒)

真题:当天的第几秒 B3847(样题)、休息时间 B4033、时间规划 B3861。

思路:把“时:分:秒”全部换算成总秒数做加减,再还原回去。

#include <iostream>
using namespace std;

int main() {
int h, m, s, k; // 起始时分秒 + 经过的秒数
cin >> h >> m >> s >> k;
int t = (h * 3600 + m * 60 + s + k) % 86400; // %86400 防止跨天
cout << t / 3600 << " " // 小时
<< (t % 3600) / 60 << " " // 分钟
<< t % 60 << endl; // 秒
return 0;
}
易错
  • 还原时用:时 = 总秒 / 3600,分 = (总秒 % 3600) / 60,秒 = 总秒 % 60,三个式子别写混。
  • 若题目明确“不会跨天”,可不加 % 86400;加上更保险。
  • 输出格式注意题目要的空格还是换行,严格照样例。

9.7 模板 6:星期推算(模运算)

真题:小杨的考试 B3921(今天星期 x,再过 n 天是星期几,0 表示星期日)。

#include <iostream>
using namespace std;

int main() {
int x, n; // x: 1=周一 ... 7=周日
cin >> x >> n;
// 先把 1..7 折算到 0(日)..6(六),再加 n 取模
int ans = (x % 7 + n) % 7;
cout << ans << endl; // 0 表示星期日
return 0;
}
易错(此处全网二手资料常写错!)

二手资料常给 (x-1+n)%7,但 n=0 时会把“周一”算成“周日”,是错的。
正确做法:x%7 把 7(周日)→0、16 保持不变,再加 n 取模,结果 0=周日、16=周一~周六,手算验证无误。


9.8 模板 7:累加求和(1 到 n 的和)

真题:累计相加 B3862、ACGO 押题 1(输入 n,输出 1 到 n 所有整数之和)。

#include <iostream>
using namespace std;

int main() {
int n, sum = 0; // 累加变量一定要初始化成 0!
cin >> n;
for (int i = 1; i <= n; i++) {
sum += i; // 等价于 sum = sum + i;
}
cout << sum << endl; // 样例:输入 10 → 输出 55
return 0;
}

进阶:公式法 sum = n * (n + 1) / 2(一句替代循环,更快更稳):

// 直接输出,避免循环写错
cout << n * (long long)(n + 1) / 2 << endl;
易错
  • sum 必须 = 0 初始化,写成 int sum;(未初始化)会得到垃圾值。
  • 数据较大时用 long long,例如 long long sum = 0;(防溢出)。

9.9 模板 8:枚举与计数(找因数 / 美丽数字 / 小明幸运数)

真题:找因数 B3953(输出 n 全部因数)、美丽数字 B4035(倍数 + 逻辑判断)、小明的幸运数 B3902(循环计数)。

#include <iostream>
using namespace std;

int main() {
int n, cnt = 0; // cnt 用于计数
cin >> n;
for (int i = 1; i <= n; i++) {
if (n % i == 0) { // i 能整除 n → i 是因数
cout << i << endl;
cnt++; // 顺便统计因数个数
}
}
// cout << cnt << endl; // 如需个数再输出
return 0;
}

优化写法(只枚举到 n\sqrt{n},一级可不讲但知道更好):

for (int i = 1; i * i <= n; i++) { // i*i<=n 比 i<=n 快很多
if (n % i == 0) cout << i << endl;
}
大白话

“枚举法”就是让 i 从 1 数到 n,挨个问“你能整除 n 吗?”能就记下来。一级 n 很小,直接 i <= n 最稳,不用优化。


9.10 模板 9:数位分离与数字反转

真题:数字替换 BW71、各类数位操作题(取个位/十位、判断回文、反转数字)。

数位分离演示

#include <iostream>
using namespace std;

int main() {
int n;
cin >> n;
int rev = 0; // 存放反转后的数
while (n > 0) {
int d = n % 10; // 取出个位
rev = rev * 10 + d; // 拼到反转数末尾
n = n / 10; // 砍掉个位
}
cout << rev << endl; // 1234 → 4321
return 0;
}
易错
  • n % 10 取个位,n / 10 去个位,二者配合循环就能拆完整个数。
  • 反转时 rev = rev * 10 + d 是“整体左移一位再补个位”,别写成 rev = d。
  • 若 n = 0 需要单独处理(while 不进循环),按题目要求补 if (n == 0) cout << 0;。

9.11 模板 10:浮点与最值(温度转换 / 商店折扣)

真题:温度转换 B4062(华氏→摄氏,浮点 + 分支)、商店折扣 B4046(满减 vs 打折取更优)。

温度转换(华氏 f → 摄氏 c=5(f−32)9c = \frac{5(f-32)}{9}):

#include <iostream>
#include <iomanip> // 用于控制小数位数
using namespace std;

int main() {
int f;
cin >> f;
double c = (f - 32) * 5.0 / 9; // 用 5.0 触发浮点除法
cout << fixed << setprecision(2) << c << endl; // 保留 2 位小数
return 0;
}

商店折扣(满 x 减 y 与打 n 折,取更便宜的):

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
double p, x, y, n;
cin >> p >> x >> y >> n;
double a1 = (p >= x) ? (p - y) : p; // 满减价
double a2 = p * n * 0.1; // 打折价(n折 = n/10)
double ans = (a1 < a2) ? a1 : a2; // 取更便宜的
cout << fixed << setprecision(2) << ans << endl;
return 0;
}
易错
  • 浮点输出要用 %.2lf(printf)或 fixed << setprecision(2)(cout),否则小数位数不对丢分。
  • (f - 32) * 5 / 9 是整数运算会得到 0 或错值,必须写成 * 5.0 / 9。
  • 三目运算符 条件 ? 真值 : 假值,记成“问号前是条件”。

9.12 模板 11:进制转换(十进制转二进制,押题)

真题:ACGO 2026 押题(输入十进制正整数 n,转为二进制输出)。

#include <iostream>
#include <string>
using namespace std;

int main() {
int n;
cin >> n;
if (n == 0) { // 特判:0 的二进制就是 0
cout << 0 << endl;
return 0;
}
string s = ""; // 用字符串从高位往低位拼
while (n > 0) {
s = char(n % 2 + '0') + s; // 余数为 0/1,转成字符,拼到最前面
n = n / 2;
}
cout << s << endl; // 样例:输入 13 → 输出 1101
return 0;
}
大白话

“除 2 取余,倒序排列”:把 n 不断除以 2 记余数,最后把余数倒过来读就是二进制。n % 2 + '0' 是把数字 0/1 变成字符 '0'/'1',+ s 拼到前面实现倒序。

易错
  • n = 0 必须特判,否则 while 不执行会输出空串(0 分)。
  • 拼字符串用 s = char(...) + s(前插)实现倒序;别写成 s = s + ...(那会变成正序)。

9.13 必考易错点速查表

把下面这些“送命题”贴在显示器上,考试前扫一眼:

错误类型错误写法正确做法
变量未初始化int sum; for(...) sum += i;int sum = 0;
整除当浮点5 / 2 得 2要小数写 5.0 / 2
浮点输出丢格式直接 cout << c;fixed << setprecision(2) 或 printf("%.2lf")
边界没考虑没处理 n=0、n=1先想最小/特殊输入
输出格式不符多/少空格、换行错严格对照题目样例
数据溢出n 大时用 int养成用 long long 的习惯
考试小贴士
  • 一级所有输入 n ≤ 10000,放心用 int 暴力,不必优化。
  • 写完后用手算一个样例对一遍输出,能避免大半错误。
  • 分支题先写 if 把“最特殊情况”兜住,再写一般情况。

9.14 随堂检测(自测 5 题)

下面 5 题覆盖五类,试着先自己写、再对照前面模板改。思路提示已给,但建议你先别看答案写一遍。

  1. (基础计算) 输入长方形长和宽,输出面积。
    💡 提示:就是 cout << a * b; —— 对应模板 1/3。

  2. (时间换算) 输入现在时刻 h:m 和经过分钟 k,输出之后时刻 h:m。
    💡 提示:全部转成分钟 t = h*60 + m + k,再 % 1440 防跨天,最后 t/60 与 t%60。

  3. (循环累加) 输入 n,输出 12+22+⋯+n21^2 + 2^2 + \dots + n^2(金字塔 B4047)。
    💡 提示:循环 for 累加 i*i,或公式 n(n+1)(2n+1)/6。

  4. (数位操作) 输入一个正整数,判断它是否为“回文数”(正读反读一样,如 121)。
    💡 提示:用模板 9 的反转,再比较 rev == 原值。

  5. (条件最值) 输入三个整数,输出最小值。
    💡 提示:模板 2 把 > 改成 <,初始值设为第一个数。

自测建议

每写完一题,用 Dev-C++ 5.11 编译运行,喂一个样例输入看输出。能 5 题全过,一级编程题就稳了。


透明标记:本回复未查询 IMA 知识库(未配置凭证),归档跳过(纯人工编写参考文档)。真题来源已在各模板括号内标注,均为公开汇总资料,建议以 CCF 官方样题为准。

SShowball OI知识手册