ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

东华OJ基础25-27题专题:循环与数位拆解的实战通关指南

2026/9/7 20:17:28 拓冰建站 浏览量
东华OJ基础25-27题专题:循环与数位拆解的实战通关指南 我到现在还记得第一次点开东华OJ时那种感觉——题目列表排在眼前一道接一道从“基础”到“进阶”分得清清楚楚。很多人刷到基础25到27题这一带就开始卡壳要么是循环边界老出错要么是“答案错误”报得你怀疑人生。其实这三道题刚好是入门阶段最典型的分水岭它们不考什么高深算法考的是你对“循环、取余、数位拆解”这些基本功到底有没有吃透。如果你正刷到这儿或者刚准备开始刷OJ这篇文章就是给你写的。我会把这三道题背后的出题意图、边界条件、常见坑位和通解思路全部摊开来讲保证你下次再遇到同类题能一眼看穿考点不再对着WA发呆。1. 整体设计与思路拆解东华OJ基础段到底在考什么1.1 三道题背后的共同考核点很多初学者把OJ刷题理解成“背代码”看到一道题就急着上网找标程这种做法在基础段尤其吃亏。东华OJ基础25到27题从题目编号就能看出来它们是同一个小模块通常围绕“数字处理与循环结构”设计。具体来说这几道题反复在考三件事第一数字的拆解与还原。给你一个整数你要能按位取出个位、十位、百位或者反过来用各位数字构造一个新数。这里的核心操作就是取余%和整除/几乎是所有数论题的入门钥匙。第二循环的边界控制。是“小于n”还是“小于等于n”是“从0开始”还是“从1开始”这一字之差往往就是AC和WA的分界线。这类题不会直接告诉你边界细节需要你自己根据题目描述推出来。第三输入输出的格式规范。东华OJ对输出格式要求非常严格多一个空格、少一个换行、大小写写错统统判错。基础25到27这三道题虽然逻辑简单却在格式上埋了不少雷比如“每个输出占一行”这种描述很多人就栽在这里。我自己刷到这三题的时候一个很强烈的感觉是这出题人很有心。它没有直接给你一道难题而是把后续所有复杂算法都会用到的基本功拆成了三道不起眼的小题埋在日常练习里。你如果只是“照着别人的思路敲一遍”顶多记住这一道题的代码换个数字、换个包装照样不会做。但你要是理解了“为什么要先拆个位”“为什么循环要从2开始”那后面刷质数筛、回文数、进制转换都会顺很多。1.2 为什么选“循环 数位拆解”作为分水岭经历过面试或者做过项目的人都知道程序员写业务代码真正天天用的不是快排不是线段树而是循环和判断。东华OJ在基础段用三道题集中轰炸循环和数位拆解就是在帮你打地基。以第25题到第27题为例它们常常是这样编排的一道题考“某种特殊数值的筛选”一道题考“最大公约数或最小公倍数的计算”一道题考“数列的叠加”。表面上看三题互不相干实际上它们共用同一个底层能力——对循环条件的设计。拿最大公约数这一题来说你当然可以直接从2枚举到n/2用笨办法找最大因子。但如果题目数据范围稍微大一点比如让你处理好几组输入每组都是大数那笨办法就会超时。这时候出题人其实已经在暗示你“如果你会用辗转相除法这道题才是满分解法”。而辗转相除法本质上也是一个循环——反复用“除数”和“余数”更新变量直到余数为0。它和数位拆解的循环是同一个套路循环体内做的操作决定了循环结束时的变量值。换句话说这三道题本质上是一道题——你要不要用数学规律去简化循环。用得好代码量少、速度快、边界清晰用不好堆一堆if分支逻辑绕来绕去最后还漏情况。这也就解释了为什么很多人在刷到25到27题时感觉“突然变难了”。其实不是题目变难了而是它从“照着题目描述翻译代码”的阶段进入到了“你需要主动寻找数学规律”的阶段。我的建议是从这三道题开始养成“先纸笔演算再上机敲码”的习惯。拿到题先在草稿纸上写几个例子看看规律再想想有哪些边界情况最后才打开编辑器。别看这个过程多花五分钟它能帮你省下晚上两小时的排错时间。1.3 刷题顺序与心态调整建议很多新手有一个误区就是喜欢按题库顺序从头往后硬肝觉得“基础25到27之后还有28到30我得快点刷完”。这种赶进度的心态在OJ上很容易崩。因为OJ题目从来不是线性的它更像一张蜘蛛网知识点之间互相牵连。你今天就算硬啃下25到27不去消化背后的数位拆解规律后面遇到“反序数”“数字黑洞”这类题照样会卡住。我的做法是刷这类基础题时不管AC不AC都强迫自己再想想“有没有第二种解法”。比如最大公约数这一题我一开始用的循环枚举AC了之后我就想如果a和b达到10的9次方这个代码要跑多久想明白了这个问题你自然就会去学辗转相除法。学完之后你的收获就不只是一道题的AC而是一整套“循环优化”的思维模型。这种思维模型才是基础25到27题真正想送给你的礼物。心态上我也建议大家不要把WA当成挫败而是当成线索。OJ给的反馈是“答案错误”而不是“运行时错误”说明你的程序能跑完但某个边界案例没算对。这时候不要急着改回头看看循环边界、初始化位置、变量类型90%的WA都能被查出来。等你刷满50道题你会发现这些Bug类型固定得很基本逃不过那“四大件”。2. 核心细节解析与实操要点2.1 数位拆解取余和整除的正确打开方式三道题里最难绕开的就是数位拆解。很多同学在纸上算能算明白一写代码就懵问题出在缺少一个具象化的理解。我来带你把“取余和整除”这事儿彻底整明白。假设现在有一个整数n 12345你想拿到它的每位数字个位n % 10结果是5去掉个位n / 10n变成1234这时候再n % 10结果是4也就是原数的十位每除一次10原数就往右“缩”一位整个过程就像你拿着一根绳子每次都从尾巴上剪一小节下来看剪完一节剩下的继续剪。循环一直持续到n变成0为止。代码写出来就是while (n 0) { int digit n % 10; // 取出当前末位 n / 10; // 去掉末位 }这个循环最妙的地方在于它对“0”的处理是天然安全的。如果n本身就是0循环体一次都不执行直接跳过。这在OJ里很重要因为很多题目会藏“输入为0”的测试点你要是用do…while循环反而会出错。还有一种常见场景是“固定位数”的拆解比如已知输入一定是个三位数要拆百位、十位、个位。这时候有些人喜欢用int a n / 100; // 百位 int b n / 10 % 10; // 十位 int c n % 10; // 个位这在“确定是三位数”的前提下是可行的但我还是建议新手用while循环去拆。原因有二其一OJ题目虽然按常理出题但为了严谨往往会有数据范围的说明如果题目说“一个三位数”那的确没问题可一旦遇到题目没说死的情况固定位数拆法会让程序变得脆直接报错或者出错误答案。其二while循环的办法可以“无脑迁移”到任何位数的题目你只要背这一种思路就能解决一大片题目学习成本是最低的。从底层原理上讲取余操作 % n 拿到的是“除以n后的余数”对于十进制数字来说n取10时得到的就是十进制下的最低位整除 / n 拿到的是“去掉最低位之后剩下的高位部分”。这个数学含义一定要刻在脑子里因为后面做进制转换时会反复用到同款思路区别只是把除数从10换成2、8或16。2.2 循环边界判断与防越界技巧循环边界是基础25到27题里另外一个“主战场”。我见过特别多的代码思路完全正确就是边界差了1然后交上去WA到怀疑人生。这里我分享一个我自己的检查套路非常简单但极管用拿到一道题先问自己三个问题。第一个问题循环从几开始如果是数组下标通常从0开始如果是枚举数字本身通常从1开始如果是枚举因子通常从2开始。第二个问题循环到几结束是小于n还是小于等于n甚至小于n/2完全取决于你的数学推导。第三个问题循环体的边界条件和循环结束条件是否互斥有没有可能死循环举一个非常经典的例子判断一个数是不是素数。新手最容易写成for (i 2; i n; i) { if (n % i 0) { printf(not prime); break; } }这个代码的问题是如果n是素数循环会跑完一遍但循环结束后没有做任何“是素数”的输出程序相当于啥也没干。这就是典型的“循环结束之后缺少收尾处理”。正确思路是加一个标志位flag初始为1一旦发现有因子就置0并break最后根据flag输出结果。这个flag标志位的用法在25到27题里极大概率会出现。还有一个更隐蔽的坑是“精度和溢出”。比如有的题要你累加一个数列数据范围给到10的9次方你用int存结果累着累着就溢出了输出变成负数然后你怎么查都查不出逻辑错误。这种坑很难靠肉眼发现我通常直接改成long long在C/C里哪怕题目数据看起来很小。养成这个习惯能帮你省下太多时间。另外一个我踩了好几次的坑是位运算和逻辑运算优先级搞混。写循环条件时我有时候习惯写成 if (n % i 0 n / i ! 1)如果忘记加括号很容易被编译器解析成奇怪的东西。虽然现在编译器对多数情况会给出警告但在线评测系统不会管你你自己得打起十二分精神。最好的习惯是条件表达式宁可多写一对括号也不要省。2.3 经典数学工具的实操化理解辗转相除法如果基础25到27题里包含“求最大公约数”或“最小公倍数”那辗转相除法就是绕不开的核心工具。这个方法的核心思想其实特别直白一句话讲完两个数的最大公约数等于较小的数和两数相除的余数之间的最大公约数。写成递推式gcd(a, b) gcd(b, a % b)一直递归下去直到余数为0当前非零的数就是答案。用循环实现代码短到离谱int gcd(int a, int b) { while (b ! 0) { int temp b; b a % b; a temp; } return a; }这段代码里有个特别容易出错的地方更新a和b时必须先保留b的旧值然后再去算a % b否则顺序一颠倒b已经被覆盖掉余数就算错了。我见过好多第一次写这个函数的同学把顺序写成 a b; b a % b;结果算出来全是0。这不是数学不会完全是变量更新的时序问题。求最小公倍数lcm就更简单了公式就是 a / gcd(a, b) * b。注意这里我把除法放在前面先除再乘是为了让中间结果尽量小一点降低溢出的概率。这是个很小的优化技巧但在数据范围大的时候能救命。你想想如果a和b都是10的9次方先乘的话积是10的18次方long long确实能存但万一题目再逼近一点可能就翻车了。我还想多说一句辗转相除法不只在“最大公约数”这类明显的数论题里有用。很多看似跟约数无关的题目比如判断互质、求不定方程的一组整数解最后都会绕回gcd。所以基础25到27题里碰到的这个工具值得你花半小时彻底吃透包括自己手写一遍处理边界情况比如gcd(0, 5)gcd(3, 7)这类特殊输入跑一跑保证程序不崩。3. 实操过程与核心环节实现3.1 准备工作搭建本地OJ调试环境聊完了思路和工具现在进入实际操作环节。我不建议你直接在OJ网页的在线编辑器里边写边改。东华OJ的在线编辑智能提示基本没有出错了以后排查起来也费劲。更推荐的做法是在自己电脑上搭一个本地调试环境代码先本地跑通再粘到OJ上提交。这样最稳也最方便你打印中间变量排查问题。如果你是C/C选手装一个Dev-C或Visual Studio Code再配好GCC编译器就行。如果用C语言记得把源文件保存成.c后缀用C则保存成.cpp。Dev-C的入门成本最低下载安装一路默认新建源文件直接开写。VS Code则需要自己配置终端编译命令稍微麻烦点但熟练后非常高效。如果你刷题用的是Java或Python那就更简单了。Python直接在官网装一个解释器然后任意文本编辑器写完命令行里跑 python xxx.py 就能看到结果。Java的话要配好JDK用 javac 编译、java 执行。我个人建议刷OJ尽量把自己固定在“一门语言”上不要“今天用C明天用Python后天换Java”。每门语言的输入输出细节差异很大比如C语言的scanf需要传地址符Java的Scanner要记得closePython的input读进来是字符串得自己转int。这种差异在OJ上最容易造成非逻辑错误而你花在排这些错上的时间真的很不值得。本地环境搭建好之后正式做题的第一步不是写代码而是“读题并画测试用例”。我的习惯是在草稿纸上先写3到5组输入手动算出期望输出。比如25题如果让你“求一定范围内的水仙花数”我就会先写下100、153、370、371、407这几个数手动确认哪些满足条件。然后写代码的时候每写完一部分就打印中间结果拿自己的测试用例去验证。等本地所有用例都通过再粘到OJ上提交。这个过程看起来啰嗦实际上能把你的AC率从五五开拉到九成以上。3.2 第25题典型实现以“水仙花数”为例东华OJ基础段里“水仙花数”这类题目出镜率特别高。虽然我没法百分百确认25到27题的原文但按照东华OJ题库的编排习惯这个位置非常大概率会出现一道“特殊数字判断/输出”题。我就拿水仙花数当样板给你完整拆解一遍。题目要求通常是输出所有三位数中的水仙花数即各位数字的立方和等于该数本身。最自然的思路就是遍历100到999对每个数做数位拆解然后判断立方和与自身是否相等。#include stdio.h int main() { for (int i 100; i 999; i) { int a i / 100; // 百位 int b i / 10 % 10; // 十位 int c i % 10; // 个位 if (a*a*a b*b*b c*c*c i) { printf(%d\n, i); } } return 0; }这段代码的核心在于数位拆解。很多人分不清 b i / 10 % 10 为什么拿到的是十位我解释一下i / 10 先把个位丢掉剩下的数再对10取余取出的就是原来十位。拿153来举例153 / 10 15然后 15 % 10 5而三位数153的十位恰好是5。这个题目有一处容易出错的地方有些同学喜欢把判断条件写成 a^3 b^3 c^3 i。注意在C/C里符号 ^ 是异或运算不是幂运算。这个错误极其隐蔽因为编译能通过只有运行结果完全不对。如果你在代码里想算“立方”最稳妥的写法就是直接乘或者调用pow函数但pow返回的是double类型和int比较时可能会有精度问题实际上三位数的三次方结果都是整数比较并不会出错但我还是建议直接用乘法干净利落。提交前你要检查题目要求的输出格式。有些题要求“每行输出一个数”有些题要求“两个数之间用空格分隔”。这里空格和换行的区别非常致命。我们在本地打印得舒服了直接printf(%d , i)输出空格然后OJ判“格式错误PE”再然后你盯着代码看半天也看不出问题。这类错误在OJ里虽然没有WA那么严重但也是零分。所以务必按照题目描述来说换行就换行说空格就空格。最后说一个进阶变体如果题目不是“水仙花数”而是“打印各位数字之和等于某值”的数思路完全一样只是把立方和改成求和。你只要把“拆解三位数”这段代码烂熟于心这类题目基本是送分题。这也是我强调“数位拆解是一切的基础”的原因。3.3 第26题典型实现以“最大公约数与最小公倍数”为例如果基础25到27题里包含最大公约数GCD和最小公倍数LCM题目那典型要求是输入两个正整数输出它们的最大公约数和最小公倍数。这类题的政治正确做法就是辗转相除法。#include stdio.h int main() { int a, b; while (scanf(%d %d, a, b) ! EOF) { int original_a a; int original_b b; while (b ! 0) { int temp b; b a % b; a temp; } int gcd a; int lcm original_a / gcd * original_b; printf(%d %d\n, gcd, lcm); } return 0; }这个代码里有几个细节值得琢磨。第一个是 while (scanf(...) ! EOF)这是一种“持续读到文件尾”的写法用于处理题目描述中“多组测试数据”的情况。OJ系统判题时输入数据在后台就像一个文件你的程序得要读完所有数据才算结束。你要是只读一组后面几组测试点就跑不到直接WA或没输出。这个写法在C语言里几乎是标配务必记牢。第二个细节是我在进入循环前先把 a 和 b 的原始值存了下来。为什么要存因为辗转相除法执行完毕之后a和b的值都被改得面目全非了a里面存的是最大公约数b是0。如果不提前保存后面没办法再算最小公倍数。这是一个非常典型的“变量被修改后仍需原值”的应用场景。第三点把“求最小公倍数”写成 original_a / gcd * original_b除了防溢出还有一个更深刻的原因数学上 lcm * gcd a * b这个等式是恒成立的。所以完全没必要用“从1开始枚举找到第一个同时能被a和b整除的数”这种笨办法。如果你上OJ后看到别人的代码比你短一半不要惊讶他们很可能就是用了这个公式。3.4 第27题典型实现以“数列求和与循环叠加”为例数列求和类题目在第25到27题区间也很常见。比如让你求 1 2 ... n或者 1 - 2 3 - 4 ... 这种交替正负的前n项和。这种题的难点不在“公式”而在“如何组织循环体内的累加逻辑”。先说最普通的累加求和#include stdio.h int main() { int n; scanf(%d, n); long long sum 0; for (int i 1; i n; i) { sum i; } printf(%lld\n, sum); return 0; }这段代码里我刻意用了 long long 来存 sum。为什么如果n可以取到100000甚至更大sum的值会迅速飙升int的最大值约21亿而1到100000的和是5,000,050,000明显超过int范围。很多初学者在这里吃到WA根本原因不是思路错就是数据类型太小。这个教训建议拿小本本记下来。再说交替正负的数列典型描述是“求 1 - 2 3 - 4 ... n”但要注意n的奇偶性。一种思路是用flag标记正负号每轮循环取反int flag 1; long long sum 0; for (int i 1; i n; i) { sum i * flag; flag -flag; }这个写法很聪明的一点是i永远递增但符号在1和-1之间不断切换。每加一项符号翻转一次。当n为奇数时最后一项是正号当n为偶数时最后一项是负号这个代码都能自然处理不需要额外判断。它的时间复杂度是O(n)对基础题完全足够。如果题目再进阶一点用“求1到n中奇数和与偶数和的差”这个角度来解交替数列那甚至不需要循环奇数个数和偶数个数可以直接算出来再用等差数列求和公式。不过这种数学优化属于“锦上添花”你先把循环解法吃透遇到数据范围卡得很死的题时再来考虑也不迟。3.5 提交与自我检查流程代码写完本地测试通过不代表就可以闭眼提交了。我给自己定了“提交前三查”的规定每次都严格执行也因此少吃了很多WA一查输入输出。输入是不是用scanf/read而不是printf/print来接收输出格式和题目的描述是否完全一致包括空格、换行、大小写如果题目要求输出“Case 1: xxx”那就必须原样输出一个字母都不能差。二查变量类型。所有可能累加、相乘的值我都问自己一句“数据上限多大现在的类型装不装得下”。是整数就优先long long不是盲目的习惯而是被爆int的教训给教育出来的。三查循环边界。for循环里写的是“i n”还是“i n”到底该不该是“n - 1”每次提交前我都重新读一遍题面里的数据范围用它代入边界值看程序会不会走到不该走的地方。这三查做完我再把代码粘到OJ的提交框里选择好语言点提交。等待结果的那几十秒其实已经不怎么慌了因为该想的坑都在本地想过了。如果还是WA我不会盲改而是打上断点或打印中间变量专门看“边界输入”下程序的计算过程。定位到出错的那一行比重新写十个版本都靠谱。4. 常见问题与排查技巧实录4.1 我最常踩的四个坑附解决方案刷OJ到现在我总结出基础段最经典的四类报错每一个都是血泪换来的对照排查就能少走很多弯路。第一类是“答案错误WA”。这个报错覆盖面最广80%的情况是逻辑漏洞或边界问题。我自己的排查顺序是先看循环边界再看数据溢出最后看特殊输入0、1、负数、极大值。有一次我写素数判断条件写成了 i sqrt(n) 但忘了包含头文件math.h结果本地编译警告但能跑OJ直接WA这个细节很容易忽略。第二类是“运行时错误RE”。通常是数组越界、除零、栈溢出。基础25到27题出现的概率略低但求最大公约数时如果你没处理b为0的输入有可能出现除零异常。或者你开了固定大小数组但输入数据比预期多也会越界。解决办法就是写代码时统一加好边界判断宁可多写几行也不裸奔。第三类是“超时TLE”。基础题出现TLE通常是因为算法太暴力比如用两层循环去筛因子数据一大就挂。应对方案是尽量用数学方法减少循环次数比如判断素数只需要枚举到sqrt(n)最大公约数直接用辗转相除法。这类优化不是可有可无的“装逼技巧”而是OJ场景下的生存技能。第四类是“格式错误PE”。这是最冤的代码逻辑一点问题没有就是多了一个空格或者少了一个换行。解决办法很简单提交前认真比对题目里的输出样例尤其是“行末不要有多余空格”这种话C语言输出时可以在循环内判断是不是最后一个元素不是才输出空格。这种处理会让代码略长但换了AC值。4.2 典型案例复盘一个WA的完整排查过程我拿自己的一次实际经历来复盘。有一道题要求输出m到n之间所有素数每行输出8个。我写完代码本地测了没问题提交却WA。当时我第一反应是“是不是格式问题”于是把输出样例截图放大逐个空格比对没发现异常。然后我开始怀疑输出个数不对又手动列了区间内的所有素数对照程序跑出来的结果发现前几行都对最后一行少了一个数。这一下就定位到问题了我的循环条件是 i n而不是 i n导致当n本身是素数时它永远不会被输出。边界值n被我漏掉了。改完这个条件重新提交直接AC。那次经历之后我特别重视“边界值与等号”的关系。你可能觉得这是小事但在OJ里边界值就是出题人最爱埋伏的地方。类似地如果题目让“输入若干个数以0结尾”很多同学会用 while (n ! 0) 做循环这是对的。但如果你用 while (scanf(%d, n) n ! 0)注意运算符优先级很容易写错成 while (scanf(%d, n) ! 0 n ! 0)两者语义完全不同。第一种是“成功读入一个数且这个数不为0才继续”第二种是“scanf返回值不等于0且读入的数不为0才继续”当输入结束时scanf返回EOF即-1不等于0可n并不是有效数字逻辑就乱了。这种细枝末节的优先级问题也建议通通加括号解决。4.3 排查心得打印调试法在OJ题中的威力很多人觉得OJ题代码短不需要调试工具直接走读就能抓住错误。但我的经验是人眼扫描代码的能力远没有你想得那么强尤其是涉及到循环几次、变量怎么变化的时候。哪怕代码只有二十行我也建议你在里面加几行printf把关键变量的值打印出来。举个例子你写了一个“计算各位数字之和”的程序输入12345期望输出15。但程序输出12。这时候不要瞎猜直接在循环里加 printf(当前n%d, 取出的digit%d\n, n, digit)一跑你就知道是哪里漏加了。跑完把这个printf注释掉再提交千万不要带着调试输出交上去否则OJ会因为你额外的输出判PE或WA。如果你用的是本地IDE还可以用断点调试但在OJ场景下printf法其实更通用、更快捷。等你不依赖调试输出就能在脑子里运行代码的时候那基本上就是入门到中级了。基础25到27题正是练习这块的好素材代码短、逻辑清晰你完全可以把它们当成“思维模拟题”来练先在脑子里过一遍运行过程再上机验证。4.4 东华OJ特有的提交流程细节东华OJ的网页端和其他OJ在细节上有一些不同。提交时要注意语言选择C语言就选CGCCC就选CG别选错。有时候有些同学本地用的是C编译器写的代码里出现了C特性但提交到OJ却选了C语言编译直接失败报“Compile Error”。反过来也有本地用C语言语法写的结果提交时选了C虽然大多数情况没问题但还是要保持一致。东华OJ对代码的入口要求是 int main() 或 int main(void)你如果写成 void main()一部分编译器会警告OJ可能直接判编译错误。习惯上还应该在main函数末尾 return 0;虽然不写不一定报错但写了更规范也避免一些编译器或评测系统产生意外行为。如果你在提交后看到“Compile Error”点开编译信息详情它会告诉你具体是哪一行哪个地方语法错了不要慌着改先看错误信息里的行号和提示大多数情况不过是少个分号、括号不匹配或者变量名打错。这些低级错误在本地IDE里常常被自动提示拦截但在OJ的文本编辑器里没有智能提示就格外容易发生。所以我还是建议本地写好、本地编译通过再粘到OJ上这能避开90%的编译类错误。5. 避坑指南与刷题进阶心得5.1 从基础25到27题延伸开去的知识脉络刷完这三道题千万别急着欢呼“终于过了”更值得做的是把这几个知识点串成一条线。25到27题涉及的核心能力——循环结构、数位拆解、最大公约数、累加逻辑这些都是后续算法专题的地基。比如“回文数”题就是在数位拆解基础上把拆出来的数字再逆序拼回去而“素数筛”题则是在循环边界的基础上引入数组标记槽位再往后走“高精度加法”“大数乘法”也要靠逐位处理和进位标记。你现在花的每一分钟都会在后边的题里加倍还回来。我自己的习惯是每刷完一批题就用一张A4纸画一个简易的“知识图谱”把这些题涉及的知识点以及它们之间的联系写下来。25到27题这个周期我可能就会写“数位拆解——相关题XX相关知识点取余/整除常见变形进制转换”。过两周翻出来看看会发现自己进步特别明显因为你能看着图说清楚“这题考什么我该用什么思路”了。这个阶段还有个重要的转折从“学语法”过渡到“学算法”。基础25到27题表面上是考C语言语法但实际上你已经开始接触“算法设计”了。比如“要不要用辗转相除法优化”就是个算法选择问题。你能主动意识到这一点说明你已经领先了大多数只满足于“AC就完事儿”的刷题者。5.2 三个能提升AC率的编程习惯借着这篇文章我把这几年刷OJ验证过的三个好习惯分享出来它们都和具体题目无关却决定你能否稳定AC。第一变量命名要有语义。很多刚刷题的人喜欢用 a、b、c 这种名字代码一长自己都看不明白哪个是输入、哪个是中间变量、哪个是结果。我习惯用 sum、gcd、digit、flag 这样的名字一是读起来顺二是出现Bug时定位快。基础题代码短这个优势不明显但一旦你写两百行三百行的代码语义化命名能救大命。第二先在纸上跑一遍样例再敲代码。哪怕是很简单的题我也坚持“手动模拟一组数据再编码”。比如25题要求输出水仙花数我会先写1531^35^33^3在纸上验证一遍等式成立再开始写拆解代码。这个过程能帮我把题目里的数学关系转成编程步骤编码时会顺畅得多。第三保持代码格式整洁缩进统一。这个习惯看着很“洁癖”但实际能减少不少低级错误。括号不配对、if块范围不清这类问题在缩进混乱的代码里极难发现但缩进一旦清晰很多错误会自己“跳”出来。OJ不在乎你的代码美观但你在乎因为你要维护和理解它。5.3 关于“题解”的正确打开方式刷题时遇到瓶颈看题解是合理且有效的但方式很重要。我的建议是“卡住半小时再看题解”。半小时以内鼓励自己死磕因为你自己想出来的思路印象最深迁移能力最强。半小时以上再去看题解重点看“它的思路和我的思路差异在哪”而不是盯着代码抄一遍。基础25到27题这个难度通常一道题看题解前应该有多种思路浮现哪怕其中一个跑不通也比脑袋空空直接看答案强。如果看完题解发现别人的代码很简洁可以想想“为什么他能想到这个技巧而我没有”这个反思过程比AC本身更值钱。另外我不太推荐“只记代码模板”的学习法。比如求最大公约数你背下那三行代码很简单但等到题目变成“给定一个分数要求约分到最简形式”你就需要真的理解“gcd返回的是什么、应该拿它去除谁”。理解本质泛化应用这才是刷题的最高效率路线。一句话总结就是不要用战术上的勤奋掩盖战略上的懒惰刷题数量重要但内化更重要。5.4 顺手做个复盘如何把刷题经验固化成自己的东西每次AC完一套题我建议你顺手填写一个小复盘模板题目编号、题目考点、我的思路、最优思路、本次代码哪里写得不顺。不用写得很长三五行就行但一定要写。这个复盘在你两周后复习时会特别有用能快速唤醒记忆让你不用重新读一遍题目才想起当时的解法。如果25到27题里你遇到了比较典型的陷阱也建议连同教训一起记下来。比如我自己的复盘笔记里有一条是“scanf读多个整数时注意%d之间的空格与换行是等价的”后来确实帮我规避了多次输入格式问题。别小看这种笔记它是你从“刷题人”进化成“竞赛选手”的阶梯。最后如果你在刷题过程中经常觉得自己“看懂了但不会写”别着急那是正常的说明你的“输入”和“输出”之间的桥梁还没建好。桥梁怎么建没有捷径就是多写、多改、多调试。基础25到27题是一个很好的起点它们足够简单到让你建立信心又足够经典到让你积累可复用的套路。把这个模块彻底吃透后面的路会越走越顺。