尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

第二天基础OJ 04-06:从输入输出到分支循环,新手刷题必备进阶指南

第二天基础OJ 04-06:从输入输出到分支循环,新手刷题必备进阶指南 第二天基础OJ 04-06从“照着抄”到“自己写”新手刷题最该迈过的那道坎如果你正在刷OJOnline Judge在线评测系统大概率对“第二天”这个节点深有体会。第一天的热情还在语法刚混了个脸熟题目打开一看中文每个字都认识合在一起不知道让它干什么。我在带新人入门算法竞赛和编程基础时见过太多人卡在这个位置不是不会写代码而是不知道OJ到底想要什么更不知道“基础题04到06”这种连续编号背后藏着一条从输入到输出、从模拟到思维的进阶暗线。这篇文章不打算讲某个OJ平台的特定答案而是把“第二天基础OJ 04-06”这个场景当作一个切片拆开揉碎讲清楚基础题到底在考什么、典型的04-06号位题目长什么样、你用什么样的顺序去思考和编码最高效、以及那些让新手原地崩溃的报错到底是怎么回事。无论你是在杭电OJ、东方博宜还是学校自建的OJ上刷题这套思路都通用。有人可能会问就三道基础题值得写这么长值得。因为这三道题的价值不在“做对”而在于让你第一次建立起“读题→设计→编码→调试→提交”的完整闭环。这个闭环一旦跑通后面几百道题都是它的重复和变形。1. 内容整体设计与思路拆解为什么OJ基础题都从“输入输出”开始1.1 OJ评测的核心逻辑黑盒测试先说一个很多新手第一天没搞明白的事OJ怎么判断你的代码对不对它不是人眼看的是拿你的程序去跑一组又一组“测试数据”。你的程序读入输入产生输出评测系统把你的输出和标准答案逐字符比对。一样就ACAccepted通过不一样就是WAWrong Answer答案错误。这种机制叫“黑盒测试”你可以把它想象成一场只有标准答案的客观题考试过程再漂亮结果不对就是不对。这就解释了为什么OJ所有题目的描述里“输入格式”和“输出格式”永远是最重要的两段话。基础题04到06往往就是围绕这两件事做文章的有的题输入两个整数输出它们的和有的题输入一个整数根据条件输出不同结果有的题输入多行数据要求你循环处理最后按指定格式合并输出。这些在高手眼里“闭着眼都能写”的题其实是评测系统最核心的游戏规则先理解数据怎么进再决定逻辑怎么写最后保证数据怎么出一个字符都不能差。理解了这层你再看题目时会发现OJ题目描述的结构惊人地一致背景故事可以略过→ 输入格式重点→ 输出格式重点→ 样例输入/样例输出用来验证你的理解。我建议新手拿到题先别急着敲键盘用两分钟把“输入格式”和“输出格式”读三遍再对照样例模拟一遍数据流向这比你多写十行注释都管用。1.2 编号04-06的“生态位”从单点计算到流程控制如果你观察过各类OJ的基础题序列会发现前几题的分布通常是有讲究的。比如杭电OJ的1000是经典的AB东方博宜的早期题号也大量覆盖“输入两个数求和”“判断奇偶”“循环打印”这类点。那么“第二天基础OJ 04-06”这个位置大概率对应的是什么呢以我看到的多数OJ题目排列习惯基本逃不出三个层级题号区间典型考察点对应C/C/Java/Python知识点01-03纯输入输出、简单运算变量定义、cin/scanf/input、基本算术04-06单分支/多分支、简单循环if-else、for/while、累加器、标志位07-10循环嵌套、数组初尝双层循环、一维数组、字符串基础也就是说04到06这三道题正好是你从“照着样例抄代码”过渡到“按逻辑写代码”的转折点。04题可能是一个带条件判断的计算比如“输入成绩判断是否及格”05题可能是一段需要循环累加的计算比如“求1到N的和”06题则可能是前两者的结合比如“多组数据每组判断奇偶并统计”。这个设计其实非常聪明。它不会一上来就让你写快排或者DP而是用三道连续小菜逼你掌握两个底层能力第一让程序“看情况办事”——也就是分支结构第二让程序“反复办事”——也就是循环结构。这两个结构是后续一切复杂算法的地基。所以别小看这三道题地基打不牢后面盖楼全是裂缝。2. 核心细节解析与实操要点三道基础题的通用解题框架2.1 读题四步法输入范围、输出格式、样例、边界很多新手包括当年的我做题喜欢“翻译题面”把中文题面读成“哦就是求个和嘛”然后甩开膀子开始写。这种习惯在前三题可能侥幸过关到04-06一定会碰壁因为题目开始出现“隐藏条件”了。我给自己带的新人定的规矩是“读题四步法”每道题强制走一遍先读“输入格式”和“输出格式”圈出所有跟数据形态有关的词“第一行”“空格分隔”“多组数据”“以EOF结束”“每个结果占一行”。再读样例自己动手在草稿纸上跑一遍确认“输入样例”经过你的理解能得到“输出样例”。然后回到题目描述找“边界词”大于、小于、不超过、非负、正整数——这些都是潜在的坑后面会考。最后问自己一个问题如果输入是最小值、最大值或者什么都不输入我的程序会怎样很多WA就出在“极端情况”上。以一道典型的“判断闰年”题输入年份输出Yes或No为例。大多数人会写能被4整除就是闰年。但题目真正的规则是“能被4整除但不能被100整除或者能被400整除”。这就是“边界词”的典型陷阱。基础题04-06里你大概率会遇到类似情况表面一个条件实际两个条件。2.2 分支结构别把if写成一条道走到黑分支结构是04-06号题的核心考点之一。它的语法很简单但新手容易犯三个毛病第一个毛病是“条件写反”。我见过最典型的错误是把if (a % 2 0)写成if (a % 2 0)——一个等号是赋值两个等号才是判断这在C/C里会直接编译报错在Python里则是逻辑错误。复习时看到这类代码一定要下意识警惕。第二个毛病是“忘记else”。比如题目要求“如果及格输出Pass如果不及格输出Fail”有人只写了if及格的情况忘了处理不及格。这时候评测数据一旦包含不及格的输入程序就什么都没输出直接WA甚至RE。第三个毛病是“else if乱嵌套”。新手特别容易把多个互斥条件写成一长串if导致逻辑重复判断。正确的做法是能用else if就用else if让程序在第一个满足的分支结束后直接跳出判断既清晰又高效。我建议新手用“判断表”来理清思路把所有可能的情况列出来标出每种情况应该走哪个分支。比如成绩判断90以上是A80-89是B70-79是C60-69是D60以下是E。把五个区间列出来再写代码基本不会乱。2.3 循环结构给重复劳动装上“计数器”循环是04-06号题另一个核心考点。常见的三种形态for循环用于知道次数的场景while循环用于不确定次数但知道终止条件的场景do-while用得相对少。新手最容易翻车的是循环里的“边界值”。举个例子题目要求“输入N输出1到N之间所有整数之和”。很多人会写for (int i 1; i N; i)——注意这个循环到N-1就停了结果少了N。正确写法是i N。这种“差一错误”off-by-one error几乎每个初学者都会犯唯一的解药就是从样例出发手动模拟一遍循环过程把i的每个取值写出来数一数对不对。另一个高频坑是“累加器初始化”。写求和、求乘积的循环前一定要记得把累加变量先归零求和用0求乘积用1。我见过太多人定义了变量却不初始化导致结果是个随机数这在本地编译器可能碰巧是0到OJ上就是莫名其妙的WA。此外如果你在04-06里遇到了“多组输入”的题比如“输入多行每行两个数输出它们的和”恭喜你这题的隐藏考点是“循环读入立即输出”。很多人的第一反应是把所有输入存下来最后统一输出——这在基础题阶段纯属给自己找麻烦。正确思路是循环一次读一组算一组输出一组。OJ是按行比对输出的你一边读一边输出和最后统一输出效果完全一样。能一次处理完的就不要开数组简单直接才是基础题的正道。3. 实操过程与核心环节实现双手离开键盘之前先想清楚这三件事3.1 从样例出发把“题面”翻译成“输入→处理→输出”我强烈建议你在写任何代码前先在注释里写出题目的“三段式”输入什么类型几个什么分隔是否多组处理是判断是循环是计算组合起来什么顺序输出每行一个结果有没有额外空格有没有“Case #”前缀以我常拿来给新人练习的一道基础题为例“输入一个正整数N输出从1到N所有偶数的平方和。”我用“三段式”拆一遍输入一个整数N。处理循环i从1到N如果i是偶数就把i*i加到一个累加器里。输出一个整数累加器结果。就这么简单。但如果你不拆直接上手写很容易漏掉“偶数”这个筛选条件或者把平方写成两倍。很多WA不是因为不会写而是因为没想清楚就动手。再举个“多组数据”的模板。代码如下C语言版#include stdio.h int main() { int a, b; // 特别注意while (scanf(...) ! EOF) 是OJ多组输入的标准写法 while (scanf(%d %d, a, b) ! EOF) { printf(%d\n, a b); } return 0; }对应Python版import sys def main(): for line in sys.stdin: # sys.stdin逐行读取天然支持多组输入 line line.strip() if not line: continue a, b map(int, line.split()) print(a b) if __name__ __main__: main()这段代码的核心价值在于“循环读入直到EOF”这个模式。在OJ语境里凡是题目写了“输入包含多组测试数据每组占一行”或者“输入到文件结束”你就要立刻想到这个模式。这是OJ刷题生涯中最常见的一个套路没有之一。3.2 样例不是万能的三个“隐藏输入”自测法样例能帮你验证理解但不能保证代码正确。我见过太多人样例过了就兴冲冲提交结果一片WA。原因是样例只给了最普通的情况而评测数据里充满了“边界值”。所以在我自己的练习流程里有一个固定动作写完代码后不急着提交先自己造三组数据测一遍。分别是“最小值”“最大值”“特殊值”。举个例子如果题目说N是正整数你就测N1最小值。如果没说上限你就测一个很大的数看会不会超时或溢出。如果题目涉及奇偶、正负、整除就各测一组。拿“求1到N的和”这道题来说。测试N1如果输出不是1说明循环边界有误。测试N100000如果秒出结果说明算法没问题如果卡顿说明你用了O(N²)的笨方法虽然这题最优解是等差数列公式。再比如输入可能是0也可能包含负数。如果题目没说正整数你就不能假设它一定是正数。在OJ里“假设了题目没给的条件”是WA的头号原因。反过来“忽略题目明确给的条件”比如忽略了“多组输入”是第二号原因。这两个坑贯穿整个OJ刷题生涯。3.3 加班加点也要搞懂的调试三板斧本地调试是每个OJ选手的必修课我把它浓缩为三招第一招printf大法。在关键变量处插入临时输出看它实际跑起来是什么值。比如循环里打印i判断条件处打印a%b的结果。这招虽然“土”但90%的问题都能用肉眼看出端倪。第二招样例分步比对。把样例输入复制到本地程序跑完把输出和样例输出逐字符对一遍包括空格、换行、大小写。很多人WA是因为输出里多了一个空格或者少了一个换行。第三招删代码法。如果实在找不出错就把代码逐段注释掉看哪段被注释后行为变化最大问题多半就在那段。这招对“逻辑分支写错”特别有效。调试完本地再对照我前面说的“三段式”检查一遍逻辑没有问题了再提交。一个合理的耗时预期是每道基础题读题2分钟设计3分钟编码5分钟调试10分钟提交后若WA再循环。如果你一道题15分钟内没AC不是题难大概率是你漏了关键信息回去重新读题。4. 常见问题与排查技巧实录那些让新手原地崩溃的OJ报错4.1 报错类型速查表分清“编译错”和“运行错”OJ的评测结果有好几种新手最怕的是WA和RE最无语的是PE和TLE。我给你整理了一张速查表可以存下来对照缩写全称含义常见原因ACAccepted通过恭喜不用查了WAWrong Answer答案错误逻辑不对、边界没处理、输出格式不对RERuntime Error运行时错误数组越界、除零、空指针、递归爆栈TLETime Limit Exceeded超时算法太慢、死循环、输入没读完MLEMemory Limit Exceeded超内存开了过大的数组或容器PEPresentation Error格式错误空格、空行位置不正确答案本身可能对CECompile Error编译错误语法错误、头文件缺失等其中“PE”是最让人又爱又恨的——它说明你的计算结果是对的但输出的“排版”跟标准答案不一致。可能是多了空格、少了换行或者大小写不一致。解法是仔细看输出格式那一栏严格按它的要求来。记住一句话OJ只认输出格式不认你内心OS里的“差不多”。RE是另一个高频杀手。你本地运行好好的一提交就RE大概率是“输入数据比你想象的大”。比如你开了int a[100]但第101个测试数据来了直接越界。解决方法是看清楚数据范围的描述数组开到上限再加个10的余量比如上限1000你就开1010。这是所有OJ老手的肌肉记忆。4.2 三个真实翻车现场从“我觉得没问题”到“原来是这里”我讲三个我带新人时真实遇到过的翻车场景你很可能也会碰见。场景一死循环。某题要求“输入若干行每行两个整数以0 0结束”。新手写了while (a ! 0 b ! 0)但忘了在循环体里更新a和b结果一提交就TLE。这类题的核心是“先读入再判断后处理”顺序一步不能错。正确模板是while (1) { scanf(%d %d, a, b); if (a 0 b 0) break; printf(%d\n, a b); }场景二输出大小写不一致。题目要求输出“YES”你写了“Yes”本地看着没问题交上去WA。这种错最冤所以提交前务必把样例输出里的每个字母大小写都核对一遍。场景三多组输入的累加变量没清零。题目说“每组测试数据输出一个结果”如果累加器定义在while循环外面就必须要每组循环开始时重新赋0。有人只定义了一次导致第一组的结果被带进第二组数据稍多就WA得摸不着头脑。这个问题极其隐蔽排查方法就是在循环体第一行打一行累加器当前值看是不是从0开始的。4.3 实战心态WA不可怕可怕的是“盲改”我发现一个规律新手第一次遇到WA最常见的反应是“改一下碰运气”比如把改成把int换成long long然后再次提交——大概率还是WA。这不是在调试这是在赌博。正确的WA排查流程是重读一遍题目特别是输入输出格式和边界条件。对着自己的代码把样例输入从头到尾手动模拟一遍看每一步变量值是多少和程序实际输出对比。如果样例没问题自己构造边界测试数据最小值、最大值、单组、多组、空输入。如果还是没问题再考虑是不是数据类型溢出比如int存不下大数要换long long。这套流程走完90%的WA都能自己定位。剩下10%可能是题目理解偏差这时候不要死磕超过30分钟先换一道题过一段时间回头再看往往一眼就能发现问题。本人在刚开始刷OJ的第三天就被一道“判断质数”的题卡了两个小时最后发现是循环边界多写了等号把判断范围扩大了一倍导致性能超时。这种经历你也一定会有没关系记录下来就是进步。5. 从“做对题”到“会做题”第二天刷OJ的正确打开方式5.1 建立自己的“代码模板库”刷OJ到第二天你手里应该有至少三个“模板”多组输入模板、循环累加模板、if-else判断模板。别小看这三个模板它们是后面一切复杂题的地基。我自己的习惯是每学会一个新套路就把它整理成笔记配上注释说明适用范围。比如“多组输入直到EOF”模板就适用于所有“输入包含多组测试数据”的题目。这个模板库的价值在于它能帮你把“思考题”变成“套模板微调”。到后期刷到中等难度的题你真正需要动脑的时间会被压缩大部分时间花在“识别套路”和“组合套路”上。而这一切都是从那几道基础题开始积累的。5.2 三道题的复盘标准AC不是终点“AC了”当然值得高兴但在OJ刷题这件事上AC只是及格线。如果你做完一道题就扔那你的水平永远停留在“会做这道题”而不是“会做这类题”。我建议每道题AC后花五分钟做三件事看题解区有没有更简洁的写法特别是别人怎么处理边界条件的。想想如果把题目条件换一下比如输入范围扩大10倍你的代码还能不能过。记录这道题踩过的坑写进错题本避免下次再犯。基础题尤其如此。04-06这种题目解法通常不止一种有人用if-else嵌套有人用switch有人用数学公式。你不必每种都写但至少要知道有这些可能。刷题不是比谁会得多而是比谁能又快又稳地把题做对。这种“稳”只能在复盘里磨出来。5.3 关于“搜答案”这件事的看法很多人刷题卡住了就搜“东方博宜oj答案1168”“杭电oj 1002”之类的关键词直接抄答案。我的态度是搜答案可以但必须带着脑子搜。怎么看答案才算“带脑子”呢第一先自己思考至少30分钟实在没思路再搜。第二搜到答案后不要只复制粘贴而是读懂它的每一行然后在本地手动敲一遍删掉再凭记忆默写一遍。第三写完提交AC后回去看这道题问自己“如果我把输入格式改一下这段代码还能不能改对”能做到这三点抄答案也是一种学习做不到抄答案等于白抄。我自己带人的经验是基础阶段可以适当看题解但每看一道题解必须独立做两道同类型的新题作为补偿。这样既不会卡死又能保证训练量。到了进阶阶段再看题解前必须保证自己已经写出了一版代码哪怕是WA的否则这题就白做了。写在最后基础题的价值不在“题目本身”而在“闭环”第二天刷OJ04到06这三道题说难听点可能连“算法”的门都没摸到说好听点它们是你构建编程思维的第一批砖石。你真正得到的不是三道题的AC记录而是完整体验了一遍从读题到提交的全流程并且第一次亲身体会到OJ是一个绝对理性的裁判它不看你写了多少行注释不看你变量命名多优雅只看你的输出是否符合预期。我在实际刷题过程中最大的体会是遇到WA别慌把它当成一次“程序在替题目告诉你哪里没理解到位”的机会。每一次报错都是你离“正确理解题目规则”更近一步的信号。把心态从“我怎么又错了”切换成“哦原来这里还有坑”你就能在OJ这条路上走得更远。最后再分享一个小技巧。如果你用的是C/C记得在代码开头加上这两行#include stdio.h // 如果涉及数学运算还可以加上 #include math.h基础题阶段很多WA其实是“输入输出方式不对”造成的。比如用cin/cout做题如果数据量稍大可能会因为同步问题TLE。这时候只要在main函数开头加一句ios::sync_with_stdio(false);就能明显提速。这类小技巧都是从一次次WA里攒出来的希望你能尽早掌握少走我当年走过的弯路。
返回列表