刷 OJ 到第五天13 到 15 题正好卡在一个门槛上。前几天你还在练“输入两个整数求 ab”这种热身题到了这个阶段题目开始真正考察你写程序的稳定性逻辑要一次想对边界条件要想全提交后面对红色状态要能冷静地定位问题。我先把结论放在这里第五天做的 13 到 15 题大概率不是送分题而是把循环、数组、整型操作以及一点点数学思维揉在一起的综合题。如果你和我一样白天有课或有工作只能抽晚上刷题那第五天是特别容易放弃的一段。前四天的新鲜感过去了题目难度开始爬坡网上搜题解的冲动也最强。我的建议是13 到 15 题不要贪快哪怕每天彻底搞懂一道也比一口气吞下五道有用得多。这篇文章就围绕“第五天 OJ 13 到 15 题”这个阶段把题型、解法、提交坑位和刷题节奏一次说透。1. 第五天刷题13到15题到底在考什么1.1 从题目序号看题单的递进规律绝大多数在线评测平台在排新手题单的时候都会遵循一条看不见的“难度曲线”。刚开始的几道题只考你会不会读入、会不会输出比如经典的 AB接下来几道题开始考分支判断比如判断闰年、比较大小再到 10 道题往后题单会悄悄把循环、数组、多组输入这些内容组合起来考。我刷过的杭电 OJ、郑州轻工业 OJ、东方博宜 OJ 等平台虽然题目编号不完全一样但规律基本一致13 到 15 题正好落在“我能写出代码”向“我能一次写对代码”过渡的区间。这个过渡不是平台故意刁难人而是必要的筛选机制。前面的题目像跑步热身让你熟悉 OJ 的输入输出格式、提交按钮、评测状态这些环境。热身结束后平台默认你已经知道 CE 是编译错误、WA 是答案错误、TLE 是超时所以题目不再手把手喂你开始要求你自己处理“题目没明说但客观上存在”的情况比如多组输入到底读到哪结束比如结果要保留几位小数比如最大值初始化该用多少。这些细节单独拎出来都不难但凑在一起就成了第一次劝退点。1.2 13到15题最常考察的三种能力第一种是多组输入与循环控制。很多第一次碰到“输入包含多组测试数据处理到文件结束”的同学会懵不知道用while (cin n)而不是cin n。这一阶段反复出现这种读入方式就是在逼你养成“读入跟着题目描述走而不是跟着自己的直觉走”的习惯。第二种是边界条件意识。0、1、最大值、最小值、负数、前导零这些词听上去很抽象但 WA 的提交里十有八九挂在它们身上。比如“把一个整数倒序输出去掉前导零”这道题输入 120 时输出应该是 21 而不是 021输入 0 时输出应该是 0 而不是空。这些细节只有你想到了代码才会对。第三种是自我调试能力。OJ 不会告诉你错在哪个输入上你必须学会自己造数据、看输出、猜原因。有人搜“西北农林科技大学 C OJ 智能指针”那是学到数据结构和现代 C 才会碰到的东西13 到 15 题阶段完全用不到不如先把边界条件练好。2. 第13到15题的典型题型拆解不同平台的第 13 到 15 题具体内容可能不同但这阶段常见的题型高度集中。我把它们归成三类你对着题单看大概率能认出来。就算你遇到的题目跟我的描述不完全一样拆题思路也通用先读清楚输入是什么、输出要什么格式再想数据范围再写代码。2.1 第13题数列求和与精度格式化这类题的典型描述是输入一个整数 n求 S 1 1/2 1/3 ... 1/n 的值结果保留三位小数。它同时考三件事累加循环、整数除法和浮点数除法之间的区别、输出格式化。第一件事不用多说for循环从 1 加到 n 就完事。第二件事是新手最容易翻车的点如果你写1 / iC 会按整数除法处理i 一旦大于 1结果就是 0最后累加出来 S 等于 1。要得到正确结果必须写1.0 / i让参与除法运算的两个数中至少有一个是浮点数。第三件事是格式化输出用cout fixed setprecision(3)就能把输出固定为小数点后三位。这类题看着简单但能一次性 AC 的人并不多。很多人卡在精度上比如题目要求四舍五入保留三位小数如果你用单精度float而不是double数据稍大一点累加误差就会被放大。能用 double 就用 double不要跟浮点进度较劲。2.2 第14题数组最值查找典型描述是输入一个正整数 n然后给出 n 个整数输出其中的最大值和最小值。这类题考数组操作和比较逻辑看起来直白实际上隐藏着初始化陷阱。新手最常见的写法是int maxv 0; int minv 0;如果 n 个整数全是负数maxv就会一直是 0答案错误如果全是正数minv又输出了 0。正确做法有两种要么把最大值和最小值都初始化为第一个读入的元素要么用climits头文件里的INT_MAX和INT_MIN。后一种思路更通用先拿一个很大的数当作最小值候选再拿一个很小的数当作最大值候选每读一个数就比一次。这道题的另一个考点是输入格式先读 n再循环读 n 个数。有些同学会把 n 当成第一个要比较的数导致少读一个数据、拿随机数去比较最终答案错得莫名其妙。我建议每道题先手动跑一遍样例把变量每一步的值写在草稿纸上这种错误基本上当场就能抓出来。2.3 第15题数字反转与符号处理典型描述是输入一个整数把它的各位数字反转后输出要求去掉前导零负数保留负号。比如输入 -120输出 -21输入 0输出 0。这道题考察整除、取模、负号处理还顺带考察“前导零”概念是这一阶段含金量比较高的题。核心思路是循环“取最后一位拼到新数字后面”。第一步先保存符号把负数转成正数处理第二步用while循环每次取n % 10把结果乘以 10 之后加上这一位第三步把符号乘回去。关于前导零实际上反转算法天然会处理掉输入 120先取出 0rev变成 0再取出 2rev变成 2再取出 1rev变成 21最后输出 21 而不是 021因为整数类型本身不会保存前导零。这道题还要留个心眼如果题目数据范围允许到int的极限比如 n 是 INT_MIN那么n -n会溢出出现未定义行为。做题前先看题目给的范围如果 n 的绝对值可能超过int能表示的范围可以直接用long long来存省心很多。3. 完整解题实操展示光讲题型还是有点虚我把这三道题的完整代码和实测流程直接放出来。以下代码我在好几个平台上跑过主要思路一致个别平台的编译器版本不同注意用 C11 或更高版本就没问题。3.1 三个题目的完整 C 代码第 13 题数列求和#include iostream #include iomanip using namespace std; int main() { int n; cin n; double sum 0.0; for (int i 1; i n; i) { sum 1.0 / i; } cout fixed setprecision(3) sum endl; return 0; }注意1.0 / i前面的 1.0 是关键不能写成 1。fixed控制小数点后的位数setprecision(3)表示保留三位小数。如果题目要求保留六位就把 3 改成 6。第 14 题数组最值#include iostream #include climits using namespace std; int main() { int n; while (cin n) { if (n 0) continue; int maxv INT_MIN; int minv INT_MAX; for (int i 0; i n; i) { int x; cin x; if (x maxv) maxv x; if (x minv) minv x; } cout maxv minv endl; } return 0; }这里用while (cin n)是因为很多 OJ 题目写的是“多组输入处理到文件结束”。如果题目只要求处理一组数据只写一次cin n也够但写成 while 循环也没错反而能应对额外测试数据。INT_MAX和INT_MIN的引入是这道题最稳妥的初始化方式。第 15 题数字反转#include iostream using namespace std; int main() { long long n; cin n; long long sign 1; if (n 0) { sign -1; n -n; } long long rev 0; while (n 0) { rev rev * 10 n % 10; n / 10; } cout sign * rev endl; return 0; }用long long是为了避免INT_MIN取反溢出的问题比较稳妥。输入 0 时while 循环不会执行rev保持 0输出0结果正确。3.2 输入输出样例怎么自测代码写完别急着提交先在本地编译器上跑几个样例确认输出格式跟题目要求完全一致。我以三组典型输入演示一遍第 13 题输入3输出1.833因为 1 0.5 0.333 约等于 1.833保留三位小数。第 14 题输入5 1 2 3 4 5输出5 1注意最大值和最小值之间是空格末尾是换行中间不能有多余的空格或逗号。第 15 题输入-120输出-21如果输出成-021或者21都是错的。整数类型不会输出前导零所以正常反转逻辑就会自动满足“去掉前导零”的要求。3.3 边界值验证清单自测样例通过只是第一步我每次提交前会过一遍边界清单n 等于 1比如数列求和只加一项n 等于 0如果题目允许看看程序会不会崩全是负数的最值查找确认 maxv 不会再输出 0带负号的数字反转确认符号没有被丢掉结尾带 0 的数字比如 120确认输出不是 “021” 而是 21可能的最大值、最小值确认没有溢出。这组清单看着琐碎但能挡住 80% 的 WA。很多同学代码逻辑大方向没问题最后就是挂在“我没想到输入会是负数”这种地方。4. OJ提交过程中的坑位速查这一节是实操中最容易卡住的部分。我把自己刷题第五天遇到过的坑、以及在群里看到别人踩过的坑都整理出来按提交后最常见的状态分类。4.1 看懂评测状态AC、WA、PE、TLE、RE、CEOJ 提交后会返回一个简短的状态很多人第一次看到错误状态就慌了。其实这些状态含义很固定状态含义常见原因ACAccepted答案正确无WAWrong Answer答案错误逻辑、边界条件、精度问题PEPresentation Error格式错误多空格、少换行、输出格式不完全吻合TLETime Limit Exceeded超时死循环、算法太慢RERuntime Error运行时错误数组越界、除零、空指针CECompile Error编译错误语法错误、缺头文件、编译器版本不兼容其中 PE 最容易让人头大。明明数据对但因为它要求每组输出之间多打一个空行或者最后一个数字后面不能有空格就被判不通过。处理办法是严格复制题面输出样例的格式不要自己发挥。4.2 编译错误与运行时错误的处理编译错误最常见的原因是缺头文件。用了cout没写#include iostream用了INT_MAX没写#include climits用了setprecision没写#include iomanip这些都属于低级但高频的错误。我的习惯是先把整道题要用的功能列出来再决定包含哪些头文件。运行时错误里数组越界是最典型的。如果你开了int a[100]但题目说 n 最大是 1000越界就是必然的。不要为了省空间把数组开得太小不确定范围时开大一个量级不会有惩罚。提示本地编译器不报错不代表 OJ 上能过。本地运行遇到越界往往会“碰巧正常”但 OJ 的评测环境可能严格得多所以数组大小的设置一定要参考题目的数据范围。4.3 答案错误与格式错误WA 和 PE 是刷题第五天最常碰到的状态。WA 要考虑边界和精度PE 要先检查输出格式。我见过一个同学第 14 题输出写成cout maxv \t minv endl;用制表符代替空格本地看是整齐提交后一直 PE改成空格立刻就 AC 了。多个测试用例时的换行也是一个常考点。如果题目要求“每组输出占一行”你就要保证每组之间没有多余空行如果题目要求“每组输出后跟一个空行”你还需要额外输出空行。判断方法很简单看样例输出里两组数据之间有没有空行。样例里没有你就不要加。4.4 超时和溢出问题13 到 15 题阶段遇到 TLE 的概率比较低但不代表不会遇到。最常见的原因是while循环条件写错导致死循环。比如判断输入是否结束时你写的是while (cin n ! 0)语义容易混乱正确写法是while (cin n)读入失败循环自然结束。溢出问题也要提前想。第 13 题如果 n 很大double一般够用但如果题目换成阶乘求和int很快就爆了要用long long必要的时候甚至要用到高精度。做题前先估一下最坏情况下的数值大小这个习惯应该从第 13 题就开始养。5. 刷题节奏与复盘方法5.1 错题本怎么写才有用第五天刷题错题本的价值开始体现。不要直接把别人的 AC 代码抄一遍贴上去那样下次还是不会。我的错题本每道题只写三行题目属于什么类型我在哪里想错了正确思路里最关键的判断是什么。比如第 15 题如果我 WA 了我会写“类型数字反转错误点没有判断负数对 INT_MIN 取反溢出关键思路先用 long long再单独存符号。”下次遇到类似题目翻一下两秒钟就能想起来比重新看一遍长篇代码有用得多。这也侧面回答了为什么我不建议搜“郑州轻工业 OJ 答案”“东方博宜 OJ 答案 1065”这类关键词。别人给出的代码不一定理解你的错误点直接抄过来你只是拿到了一个 AC失去了发现问题、修正思路的完整训练过程。真正想要答案就把题目类型、自己的代码和错误提示记下来自己对比解决。5.2 一天刷多少题更合适如果你每天能保证一到两小时我的建议是每天 3 到 5 道新题其中至少 1 道是自己花 20 分钟以上硬想出来的。第五天做到 13 到 15 题正好处在这个量级。如果时间不够只做一道难一点的题、把它的边界情况和输出格式完全吃透也好过刷十道简单题。还要提醒一点刷题最怕的不是做得慢而是断档。中间落了一两天回来发现判断输入的方式忘了、格式化输出又不熟心态很容易崩。宁可每天只写十几行代码也要把“每天碰一碰 OJ”这个习惯续住。等过了第十天、第二十天回看第五天这个阶段你会发现自己对 WA 的恐惧已经淡了很多。6. 关于第五天刷题的三点体会最后说几句个人感受也算不上总结只是我在带着不少人做过这个阶段之后最想强调的三件事。第一抄题解的时代在第五天就应该结束。前面几题你还可以通过模仿建立手感13 到 15 题开始模仿不来了你必须有自己排错的能力。每 WA 一次都对题目逻辑多一层理解这种积累是题解给不了的。第二不要觉得“第五天才做到 15 题”很慢。OJ 刷题比的不是数量而是稳定性和熟练度。我见过有人一天刷二十道结果连循环边界都没真正理解也见过有人一周只刷十几道但每一道都能讲清楚为什么这么写。后者到了后期题目变难时适应速度反而更快。第三把边界值测试当成肌肉记忆。这阶段练的三道题型本质上都在反复训练同一件事你写的代码能不能应付极端输入。这个习惯越早养成后面遇到字符串、数据结构、搜索算法时就越省心。我在实际刷题中踩过几次坑之后已经形成条件反射代码写完先跑 0、1、负数、最大值四组数据再跑正常样例。你也值得试试。