资讯动态

OJ题库刷题避坑指南:从输入输出到判题机制全解析

发布时间:2026/10/22 13:52:06 来源:尧图企业网站定制
简介面向计算机专业学生与编程爱好者杭州电子科技大学OJ题库收录5743个HTML题目页面覆盖排序、搜索、图论、动态规划等经典算法与数据结构训练题。压缩包内共5743个html文件体积约53.36MB每个题目页面均包含题目描述、输入输出格式、样例测试数据等核心信息便于离线查阅与集中练习。目前已有2127人下载学习热度可观。通过逐题研读与编码实践读者可系统锻炼算法设计、代码实现与调试排错能力尤其适合备战国际大学生程序设计竞赛ACM/ICPC或应对机考面试。题库按题目ID组织结构清晰可快速定位目标难度区间是个人刷题提升或课堂配套训练的高性价比资料。1. 打开某高校OJ题库先别急着刷题它考核的是读题与输入输出纪律第一次点开某高校OJ题库的人十有八九从AB开始以为就是读两个整数再打印和。提交后却连续吃Wrong Answer或Presentation Error卡到怀疑编译器有问题。真正常被忽略的是读题细节题目要的是“多组输入直到文件结束”而不是你理解的一组数据。这套题库本质上是一台无情的裁判不看你解题过程多优雅只按约定好的输入输出逐字符比对结果。它适合三类人准备后端岗位笔试的求职者、考研机试选手、以竞赛为目标的入门者。把题库刷到两三百题能练出对边界条件、EOF、64位整数和复杂度估算的直觉比单纯读算法书更管用。下面从注册账号开始完整走一遍提交流程再把高频翻车点逐条排掉。2. 在OJ题库跑通第一份代码注册、编译器与AB的最短提交路径2.1 注册与编译器选择判题机支持哪些语言为什么C/C最稳妥注册流程不复杂用户名、邮箱、密码部分题库需要邮箱激活个别老平台还要求用学号或邮箱前缀做用户名注册前先看清楚规则。账号信息务必记牢很多OJ不支持改用户名密码找回基本靠绑定邮箱。语言选择上我一般先看题库支持哪些编译器。常见的是GCC C、G、Java、Python。对比表如下语言典型判题环境常见风险GCC CLinux gcc通常按C99编译printf/scanf格式写错是WA第一来源Gg默认标准可能停留在C98使用C11新特性会直接CEPythonPython 3.xinput()读入大输入时效率低容易TLEJavaOpenJDK主类必须叫Main否则CE我建议新手优先选GCC C或G。原因有三运行快同样代码几乎不会因为常数太大被卡超时判题结果稳定不像某些解释型语言在不同版本下有差异题库里老题目的题解九成以上是C/C抄作业也有参照。注册完先别急着写题花两分钟确认编译器版本。如果题库提供“C11”选项就优先选它如果只能选“C”后面写代码就要主动避开C11语法。用C也一样标准选C99比较稳某些老题面里C89也能过但C99的for循环内声明变量更省心。2.2 用C语言提交AB代码模板与一次完整提交流程AB题目面虽然写着“输入两个整数”但样例输入往往是两行多组数据。标准C模板如下#include stdio.h int main() { int a, b; while (scanf(%d %d, a, b) 2) { printf(%d\n, a b); } return 0; }scanf的返回值是成功读入的变量个数。读到文件结尾时返回EOF也就是-1读到合法整数但缺一个时返回1只有两个都读进来才返回2。这里用 2而不是! EOF是判断“这次确实读到了一对数据”读入不完整就退出循环逻辑更严谨。%d对应int类型的输入输出\n在printf里是换行。OJ判题时对行尾换行并不强制但输出中间换行是必须的。提交流程是打开题目页选择语言下拉框选GCC粘贴代码点提交然后等待返回状态。第一次提交后大概率见到以下几种状态状态含义Accepted通过输出与期望完全一致Wrong Answer输出内容和标准答案不一致Presentation Error输出内容一致但空白字符位置不对Time Limit Exceeded超时程序跑得太慢或陷入死循环Memory Limit Exceeded超过内存限制常见于开超大数组Runtime Error运行时崩溃数组越界、除零、野指针等Compile Error编译错误编译器报错Output Limit Exceeded输出超限多半是调试输出忘删看到Compile Error不用慌点开详情看编译器第一行报错八成是缺头文件或int类型拼错。我习惯在本地先编译通过再提交本地用的是Windows也能装MinGW和评测机同为gcc能过滤掉大部分编译错误。2.3 用Python提交AB读取方式与C的差异如果题目允许Python而且你确实不熟C也可以用Python交。Python读取的标准写法import sys def main(): for line in sys.stdin: line line.strip() if not line: continue a, b map(int, line.split()) print(a b) if __name__ __main__: main()sys.stdin按行迭代读到文件结束自动退出strip()去掉行尾换行split()把一行按空白切成字符串列表map(int, ...)转成整数print自带换行等价于C的printf(%d\n, ...)。区别在于C的scanf对空白字符很宽容多个空格和换行都能连续跳过Python的split正好也按空白切分所以这题几乎不用关心具体分隔。需要注意别用input()逐行读十万行的输入场景下它的内部缓冲不如sys.stdin快可能被卡TLE。真有超大输入时可以用sys.stdin.buffer.read().split()一次性读出全部数据再迭代但新手没必要一开始就上这个写法。3. 输入输出格式的四道关卡EOF、多组输入、字符串与64位整数很多人在这个题库里WA到怀疑人生回头查代码逻辑也没错。其实问题不在解法而是没看懂OJ的输入约定。本OJ题库的题目面里输入描述常见“多组测试数据”“输入包含多行”“以EOF结束”这类措辞理解错一处整题白做。3.1 EOF与多组输入scanf返回值怎么用while循环为什么是标准写法先看第一类写法题目说“输入包含多组数据每组一行两个整数”。C代码应该是#include stdio.h int main() { int a, b; int ret; while ((ret scanf(%d %d, a, b)) ! EOF) { printf(%d\n, a b); } return 0; }这里改成! EOF是因为题目只要求“读到文件尾”并不要求每次都成功读到两个数。两种写法在标准输入下结果一样区别在于遇到格式异常时! EOF可能因返回0而无限循环。所以我的习惯一直是能用 2就用 2把判断收得越紧越好。另一种常见的输入约定是“第一行是一个整数T表示测试组数后跟T行”。对应模板#include stdio.h int main() { int T, a, b; scanf(%d, T); while (T--) { scanf(%d %d, a, b); printf(%d\n, a b); } return 0; }T--先判断T是否为0再自减。如果T初始为3则循环体执行3次。这个写法比for (int i 0; i T; i)快不了多少但很多老C题解里全是while(T--)你至少得能看懂。注意区分这两种约束读到EOF的题如果套T组模板只会读取第一组或直接scanf返回EOF崩溃反过来声明T的题如果用EOF模板末行会多输出一个换行或空行。每拿到一道题先看输入描述的第一句话圈出“EOF”还是“T组”。3.2 字符串与行读取getline、gets与scanf(%s)的边界字符串题比整数题更容易翻车。scanf的%s按空白分割遇到空格、Tab、换行都会停。如果题目要求“输入一个可能包含空格的字符串”再用scanf(%s)就只会读到空格前的部分后续内容全被当作下一组数据。处理整行输入C里用getline最稳#include iostream #include string using namespace std; int main() { string line; while (getline(cin, line)) { if (line.empty()) continue; cout line endl; } return 0; }getline(cin, line)每次都读取一整行包括行内空格遇到换行符停止并丢弃换行符。读到文件结束时返回false循环退出。line.empty()跳过空行防止题目给的数据末尾多一个空行导致程序把空行也当数据输出。C语言里对应的是fgets#include stdio.h int main() { char buf[1005]; while (fgets(buf, 1005, stdin) ! NULL) { fputs(buf, stdout); } return 0; }fgets需要指定缓冲区大小最多读入size-1个字符避免越界。注意老教材里的gets()在新版C标准中已被移除OJ判题机里用gets基本必CE。混合读取整数和字符串是另一个常见场景放在第4章踩坑里细说。这里记住一个原则需要保留空格就逐行读不需要空格就scanf或cin不要在一道题里混用两套读取体系。如果必须混用先消费掉缓冲区的换行。3.3 64位整数与精度大数题目用错类型就直接WA看题面数值范围是入门必修课。int在评测机上通常是32位最大能表示2147483647。如果题目说a和b在10^9量级它们的和或乘积很容易超过int上限溢出后变成负数提交WA。标准模板#include stdio.h int main() { long long a, b; while (scanf(%lld %lld, a, b) 2) { printf(%lld\n, a b); } return 0; }类型对照表类型典型位数输入格式说明int32位%d加减乘超过约21亿就危险long long64位%lld范围到约9e18竞赛常用double64位%lf浮点输出用%.3lf等格式float32位%f精度低不推荐用于OJ%d、%ld、%lld三个格式符经常被弄混。Linux下long是64位%ld匹配它但老OJ平台的判题机是64位Linuxlong long统一用%lld新手直接记死这一点整数大范围就上long long配合lld格式血泪经验。浮点题同样有坑。判断浮点数相等别用if (x y)因为二进制浮点无法精确表示十进制小数要用fabs(x - y) 1e-6并配合printf的精度控制输出。注意OJ的评测机通常是64位Linuxsizeof(int)4sizeof(long)8但不要因此依赖long的位数标准并没有保证它固定64位。跨平台写法统一使用long long最安全。4. 避坑OJ题库最常见的5个翻车点从PE到程序崩溃下面这些坑我基本都在这个题库里踩过。每条都按“现象→原因→解决”写照着排查能省掉很多无效提交。4.1 输出多了一个空格Presentation Error不是Accepted现象样例在本地跑出结果和答案一模一样提交后返回Presentation Error。原因行尾多打了一个空格或者最后多输出了一个空行。OJ的判题程序先忽略所有空白字符做一次宽松比较如果宽松比较通过但严格比较不通过就报PE如果宽松比较都不通过则是WA。PE是“你离AC就差一个空格”的经典信号。解决输出序列时不要给最后一个元素加空格或换行改成前导空格控制for (int i 0; i n; i) { if (i) printf( ); printf(%d, a[i]); } printf(\n);这段代码通过if(i)在非首元素前输出一个空格行尾没有多余空格。很多输出数组、输出因子、输出路径的题都适用。宁可多写两行判断也别在行尾留空白。4.2 scanf与getline混用读到空行现象先用cin n读整数再用getline(cin, s)读字符串结果s是空的。原因只消费了整数的字符行尾的换行符还留在输入缓冲区里。紧接的getline立刻读到这个换行符直接返回空串。解决在切换读取方式前清掉残留换行int n; string s; cin n; cin.ignore(); // 吞掉第一行末尾换行 getline(cin, s);cin.ignore()默认只丢弃一个字符如果数据文件是Windows换行\r\n需要cin.ignore(1024, \n)。更稳的办法是全部用getline读行再用stringstream解析string line; getline(cin, line); stringstream ss(line); ss n;这样整个程序只用一个读取体系缓冲区永远一致不会出现“后半行丢失”的玄学问题。4.3 数组越界本地能跑OJ上就是Runtime Error现象Dev-C或Visual Studio里运行正常提交后返回Runtime Error。原因越界是未定义行为。本地环境里越界后踩到的可能是没有人用的内存所以程序没崩评测机内核或内存布局不同或者题目数据更大越界直接踩到非法地址。解决数组开大一点并养成常量宏的习惯const int MAXN 100005; int a[MAXN]; for (int i 1; i n; i) { scanf(%d, a[i]); }如果题目最大n是100000数组长度不要只开100000开到100005甚至100010。下标从1开始时a[n]是合法位置但相应地全局数组长度就要预留n1。动态数组vector也一样检查索引是否小于size不能因为“push_back过”就认为访问安全。4.4 多组数据的全局变量与初始化现象第一组数据结果正确第二组以后答案越来越离谱。原因多组输入的题目程序只跑一遍但循环处理多组数据。计数器、标记数组、dp数组如果在每组开始时没有清空上一组残留值会直接污染下一组。解决每组数据开始时显式重置int vis[1005]; while (scanf(%d, n) 1) { memset(vis, 0, sizeof(vis)); // 本题处理逻辑 }memset按字节填充适合清零或者全部填成-1。如果要把int数组填成某个非0非-1的较大值用STL的std::fill更准确fill(vis, vis 1005, 0);另外局部数组不初始化时栈上可能是任意值全局变量默认0。我的建议是需要大量计数或标记的数组直接定义成全局变量并且仍然在每组数据开头显式清一次。这样既避免栈溢出也杜绝了残留值问题。4.5 编译器版本差异本地新特性编译通过提交CE现象用stoi、to_string、auto写代码本地编译器正常提交后Compile Error。原因部分OJ的默认编译器标准是C98stoi、to_string、unordered_map都是C11才有的特性旧标准下直接CE。解决提交时优先选C11选项如果题库不提供就用替代写法#include sstream int to_int(const string s) { stringstream ss(s); int x; ss x; return x; }这个to_int函数用stringstream解析字符串成整数不依赖C11。和atoi相比它对非法字符的处理更安全atoi(12abc)返回12容易掩盖输入异常stringstream会停在第一个非法字符位置报错路径更清晰。同理boolalpha、lambda表达式、auto关键词在旧标准下都可能CE。提交前看一眼题目页的Compiler选项养成“语言版本先确认”的习惯。5. 把题库刷出效率按主题分组、提交前自查与单题时长控制5.1 按主题刷而不是按题号刷给题库划分可积累的模块刷题最忌讳按题号从1到1000逐个往下做。同一套题库里题目难度分布不线性靠题号顺序刷很容易卡死在某个中期难题上。我一般把题库分成几个主题逐个击破主题建议题量核心目的输入输出与模拟20道读题、格式化输出、EOF处理字符串处理20道行读取、分割、匹配排序与二分20道复杂度意识、边界索引搜索DFS/BFS20道状态设计、去重、连通性动态规划20道状态转移、边界初始化图论与数学按需进阶扩展每个主题连续做下来套路会自然浮现。同一类题做到第10道时基本就能分辨“这题考的是状态初始化还是转移顺序”。5.2 提交前自查三次验证错题立刻看题解重写我给自己定的提交前检查只有三步。第一步样例跑通但样例只是最低要求。第二步构造边界数据n0、n为最大值、全空串、只有一行输入、输入中间含空行。第三步估算复杂度评测机1秒通常能跑约1亿次加法双循环超过一万就危险超过十万基本必TLE。本地批量验证可以用一个bash脚本for f in test/*.in; do ./a.out $f out.txt if diff -q out.txt ${f%.in}.out /dev/null; then echo $f OK else echo $f FAIL fi done用法是把样例输入存成test/1.in期望输出存成test/1.out脚本逐个执行并对比。diff -q只报告是否不同需要忽略行尾空格差异时改成diff -w。错题处理同样有规矩。超过45分钟做不出来就翻题解看懂后把题解关掉自己重新写一遍提交通过这道题才算真正过去。当年我的某道搜索题卡了三天最后发现是状态判重的标记数组没有在每组数据前清零根源和上面第4.4节的分毫不差。这之后我坚持单题限时、克制翻题解AC率反而上来了刷题思路也比之前清晰很多。希望你也能在这套题库里少走这些弯路。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑