
简介杭州电子科技大学在线OJ第1000至1099题的C/C代码合集面向ACM初学者、算法竞赛选手以及准备笔试的编程学习者。合集覆盖动态规划、贪心策略、深度搜索、数论推导、数据结构等常见考点代码均已调试通过可直接运行验证。压缩包共90个文件以62个cpp源文件与16个c源文件为主体附带少量调试与工程配置辅助文件整体仅1.1MB下载方便目前已有1835人学习下载。从Max Sum的动态规划、FatMouse Trade的贪心策略到Tempter of the Bone的DFS剪枝、Humble Numbers的数论递推再到Tian Ji -- The Horse Racing的贪心与博弈大量经典题目的实现既兼顾正确性也注重时间与空间复杂度的优化读者可对照代码分析算法思路学习边界条件处理、性能调优和测试调试方法从而在OJ实战中稳步提升编程与算法能力。这些示例代码能够帮助初学者跨越从理论到实战的鸿沟也为有经验的读者提供不同解法的对照与灵感。1. 杭电在线OJ 1000–1099一百道题为什么值得你一行行敲完OJ刷题圈里流传着一句话杭电OJ的1000到1099是老玩家口中的新手村。可真正刷过的人都知道新手村并不温柔。打开题库1000这道AB问题摆在那里提交数比后面很多题高一个量级看起来人畜无害交上去却不是人人AC。很多人搜“杭州电子科技大学在线oj_1000-1099代码”想找一份能直接提交的参考答案但我的意思是这一百道题最值钱的不是那一百个AC结果而是你从“对着样例写代码”进化成“对着题面约束写代码”的过程。这篇笔记适合刚接触OJ的学生、准备刷题找手感的转行者以及带新人的学长。目标就一句话让这一百道题变成你手里的第一套代码模板而不是收藏夹里的一百个链接。2. 判题系统的工作原理先搞懂OJ怎么“审判”代码再想AC在线判题系统本质上是一个黑匣子你的代码被编译喂进标准输入数据然后把标准输出和标准答案逐字节比较。这意味着一个空格、一个换行符都会被纳入比较和本地“肉眼看对”完全是两回事。在杭电OJ这类传统OJ上几乎所有的WA、PE都是因为没想明白这一点。这一章先把判题状态和输入输出类型讲透再给一个可以直接用的C提交模板。2.1 判题状态不是玄学WA、PE、TLE、MLE分别指认哪类错误第一次提交看到的结果大概率不是“通过”而是一串字母WA、PE、TLE、MLE、RE。每个状态都对应一类具体问题。状态含义常见原因ACAccepted通过无WAWrong Answer答案错误逻辑错、数据类型错、多组输入只算了一组PEPresentation Error格式错误输出多了或少了一个空格、空行TLETime Limit Exceeded超时死循环、算法复杂度过高MLEMemory Limit Exceeded超内存数组开太大、递归过深RERuntime Error运行时错误数组越界、除零、野指针WA是前100题里出现最多的情况PE其次TLE和MLE在这个阶段相对少见但出现时排查方向完全不同。判断状态指向哪里时别急着改代码先把题目里的输入约束、输出格式、数据范围抄在纸上再照着代码一条条对。很多人一WA就删代码重写重写三遍还是WA因为根子不在逻辑在输入处理。提示OJ判题只比较你的输出结果不关心方法和标准答案是否一样。一个AC代码未必是最优解但一定满足输出格式。2.2 多组输入从1000这道AB开始养成读EOF的习惯杭电OJ前100题在输入格式上大概有三种流派多组输入直到文件结尾也就是EOF先输入一个整数T表示组数再读T组单组输入读完就结束。很多人栽在第一种上本地用样例数据跑输出完全一致交上去却WA。原因是判题系统会用多组数据喂你的程序你只处理了一组就退出后面的输入没人消费输出自然不完整。C语言处理“多组输入直到EOF”的标准写法#include stdio.h int main(void) { int a, b; while (scanf(%d %d, a, b) ! EOF) { printf(%d\n, a b); } return 0; }这里要理解scanf的返回值它返回成功读入并赋值的参数个数。scanf(%d %d, a, b)成功读入两个数时返回2读到文件结尾时返回EOF通常是-1。所以while(scanf(...) ! EOF)能保证数据存在时一直处理。更严格一点的写法是while(scanf(%d %d, a, b) 2)对输入里混入非法字符更敏感。两种写法都常见我更推荐 2排查时少一层迷惑。如果是“先给组数T”的格式int T; scanf(%d, T); while (T--) { int a, b; scanf(%d %d, a, b); printf(%d\n, a b); }这套模板要练到不用过脑子就能写。如果题目要求“读到两个0终止”循环里加一个判断while (scanf(%d %d, a, b) 2) { if (a 0 b 0) break; // 处理逻辑 }2.3 一个能少踩一半坑的C提交模板头文件、主函数、返回值初学者写了一段自认为正确的代码交上去却收到编译错误原因往往是头文件不全、返回值类型不对、或者用了旧标准函数。我在杭电OJ刷前端时默认用一个相对完整又不会拉高编译成本的模板#include stdio.h #include string.h #include stdlib.h #include math.h #define MAXN 1000005 int main(void) { int a, b; while (scanf(%d %d, a, b) 2) { printf(%d\n, a b); } return 0; }stdio.h是输入输出必需string.h和stdlib.h分别对应字符串函数和排序math.h留给浮点计算。MAXN是缓冲上限数组长度需求不明时按这个量级开但要先看题面约束开太大可能MLE。int main(void)比void main()更标准return 0表示正常结束漏掉它可能在某些编译环境下不报错但没必要赌。还有一个常见要求是“每组输出占一行”。printf(%d\n, ab)末尾的\n不是顺手加的它是“行模式输出”的标准形态。如果写成%d系统比对时认为你缺换行轻则PE重则WA。3. 按题型拆解1000–1099刷题顺序和题型打法拿到一百道题不要从1000一路点着AC下去到第1020题左右就会觉得无聊。更有效的做法是先把题面按“输入输出格式”和“解题套路”粗分集中处理同类型题目。算法题真正的复杂度往往不在“算法”本身而在“如何把算法塞进这份输入输出格式里”所以按题型刷等于在短时间内反复训练同一类肌肉记忆。以下五类基本覆盖前一百题的主力。3.1 先看输入输出数据范围判断一道题属于哪一类一分钟就能确定拿到题别急着看样例先读Input和Output两段。Input会告诉你数据量、类型和组织方式Output会告诉你要不要输出Case标记、保留几位小数。把这些要素组合起来就能判断这道题该用哪个套路。我一般会在草稿纸上记三行数据范围是否多组输入输出格式。数据范围决定int还是long long、数组开多大多组输入决定主循环写法输出格式决定printf的格式串。这三个问题回答完题目已经解了一半。不要一上来就看样例数据然后if硬写样例只能帮你验证思路不能帮你定义正确行为。3.2 基础运算与AB变形练的是scanf、printf和浮点格式串前一百题里相当数量是AB的变形两个整数求积、两个浮点数求和、给半径求面积、做幂运算。算法上没难度坑全在格式。输出%.2lf表示保留两位小数的double%.3f只适用于float。很多人在本地看到输出正确交上去WA就是因为浮点类型和格式串没对齐。处理这类题背熟几组格式串整数用%d长整数用%lld单精度用%f双精度用%lf字符用%c字符串用%s。%lf和%f错位在本地可能不报错但跨编译器行为不一致属于最典型的“样例过了却WA”。如果你卡了一道题很久把输出格式串逐字符对着题面检查大概率是漏了小数位或多了空格。3.3 排序题手写快排还是直接qsort排序题在前一百题里会以“从大到小输出”“按某规则排序后输出”的形式反复出现。这里有个选择手写快排还是用库函数。我的看法是练习阶段两种都要会提交时优先用库函数。手写快排在边界条件上一出错就是RE或WA库函数经过充分验证只要比较函数写对就稳。C语言的qsort需要写一个比较函数int cmp(const void *a, const void *b) { int x *(const int *)a; int y *(const int *)b; return (x y) - (x y); }(x y) - (x y)比直接return x - y安全因为int差值可能溢出一旦溢出排序就乱。很多老手在排序题上吃过这个亏数据接近int边界时x - y溢出成负数排序结果完全错乱。降序就把比较逻辑反过来。排序题只是套模板前提是模板本身稳。3.4 字符串题字符数组、scanf(%s) 与换行符的纠缠字符串处理题前一百题里不少而且是WA高发区。C语言字符串本质是字符数组末尾要留空间给\0scanf(%s)以空白字符为分隔符读不了带空格的整行老教材会教gets但它在C11标准里已移除虽然老编译器还能用却不值得为它养成坏习惯。我的通用做法是需要读一行的题优先用scanf(%[^\n], s)读“直到换行符之前”或者fgets(s, sizeof(s), stdin)再手动去换行s[strcspn(s, \n)] \0;strcspn(s, \n)返回换行符下标替换成字符串结束符。另一个容易犯的错是上一行输入结束缓冲区残留换行符下一行读%c或%[^\n]直接读到空内容。排查这类输入错乱先打印刚读到的字符串长度和ASCII码别凭空猜。3.5 简单数学与递推为后面的动态规划做热身前一百题还有一批数学题最大公约数、判断质数、算阶乘、求斐波那契某一项。本身难度不高却是在为DP做铺垫。比如斐波那契写成递归int fib(int n) { if (n 1) return n; return fib(n - 1) fib(n - 2); }代码确实简单但数据到45以上递归调用次数爆炸轻则TLE重则栈溢出。我会改成数组递推从f[0]一路推到f[n]这是前一百题里第一次真正意义上的“用空间换时间”也是动态规划的启蒙。这里还要提long long。斐波那契第47项左右就超出int范围很多WA不是算法错而是数据在int里翻车。养成习惯凡是加法乘法先看数据范围累加结果可能超过21亿就用long long输出用%lld。4. 可复现的AC流程从样例、边界到对拍一套方法打一百题光知道题型还不够需要一个能稳定执行到提交的工作流。这套流程对1000–1099所有题都适用后面难题也很少失效。每一步都是可重复动作不靠灵感。4.1 做题四步读题面、跑样例、自造边界、复盘第一步通读题面把Input和Output段里所有约束抄下来。第二步把Sample Input复制到本地跑一遍确认能过样例。第三步是很多人偷懒的地方自己造边界数据。题面说“两个整数不超过10^9”就试两个10^9也试负数、零、最大值加一。很多WA在边界数据上一跑就现原形。第四步提交AC后回头看题解想自己的代码有无冗余或隐患WA就根据返回状态回到相应步骤排查。这套流程的核心是第三步因为OJ隐藏测试数据几乎都包含边界值。样例只是热身用的不是给你兜底的。谁把样例当标准谁就会被WA上课。4.2 从AB出发C语言版的注释级模板把多组输入和“Case x:”输出合起来就是能覆盖前100题近半需求的主框架#include stdio.h int main(void) { int T, a, b, caseNo 1; scanf(%d, T); while (T--) { scanf(%d %d, a, b); printf(Case %d: %d\n, caseNo, a b); } return 0; }caseNo从1开始每次输出后自增正好对应“Case 1: 3”格式。有些人会先printf(Case %d: , caseNo); caseNo;再输出一旦中间有多个输出分支容易漏加。把caseNo直接放进格式串更不容易错。如果value有浮点精度要求就替换成%.2lf之类其余结构不动。4.3 Python解法sys.stdin.buffer与性能边界拿Python刷杭电OJ前100题完全可行但有几个性能边界要提前知道。最简单的按行迭代import sys for line in sys.stdin: a, b map(int, line.split()) print(a b)几万行输入通常没问题。但如果TLE先别怀疑算法把输入读取改成一次性读取import sys data sys.stdin.buffer.read().split() it iter(data) for a in it: b next(it) print(int(a) int(b))s:sys.stdin.buffer.read()一次把整个缓冲区读进来返回字节串数组split()按空白切分比逐行readline少很多系统调用。对杭电这类老OJ这招常能把TLE救回来。但前100题里也有少数题对Python不友好连续TLE且算法已经最优就换C语言不是Python不行是OJ时限本来按编译型语言设置。4.4 用“对拍”验证自己的代码一个笨但可靠的方法对拍指用一个肯定正确但可能很慢的暴力程序和一个正在优化的程序在相同随机输入下比较输出。前100题大部分用不上但某道题怎么也想不通时对拍能快速定位哪个case出问题。一个极简Python对拍框架import random import subprocess for _ in range(200): n random.randint(1, 10) with open(in.txt, w) as f: f.write(f{n}\n) f.write( .join(str(random.randint(0, 1000)) for _ in range(n))) ans1 subprocess.run([a.exe], stdinopen(in.txt), capture_outputTrue, textTrue).stdout ans2 subprocess.run([b.exe], stdinopen(in.txt), capture_outputTrue, textTrue).stdout if ans1 ! ans2: print(mismatch at, _) break这段脚本把同一份随机数据分别送给两个本地程序比较输出。平时用不上但卡题一小时以上时生成几百组数据比盯着屏幕干想要快得多。5. 避坑清单1000–1099阶段最常见的五个翻车点这个区间踩过的坑翻来覆去就那么几条。下面列五条最具代表性的每条都是“现象→原因→解决”。如果你在某道题反复WA按这个清单逐条核对大概率省下一下午。5.1 Sample过了却WA多半是多组输入没读完现象本地用Sample Input运行输出和样例一模一样交上去WA。原因主循环用了if而不是while程序只处理一组数据就退出OJ用多组数据喂程序时输出不完整。解决所有“直到EOF”型题主循环用while (scanf(...) 2)先给组数的用while (T--)。把这条写成笔记后面八成水题靠这个避坑。5.2 输出多一个空格或者少一个换行PE与WA的模糊地带现象交上去返回PE有时直接WA。原因OJ比对输出流不是肉眼。题面写“每个数字之间用一个空格隔开行末无多余空格”你却在行尾打了一个空格系统一比就现形。解决输出前数清楚自己要打出的字符序列。循环输出数组时先输出前n-1个“数字空格”最后单独输出第n项并换行这样永远没有多余空格。5.3 数组越界与段错误开数组前先看约束范围现象交上去RE本地偶尔还能过。原因题面说数据最多100000个你只开了int a[1000]数据一多就越界写把程序内存冲乱行为不可预测。解决先看Input段范围再定数组大小字符串数组多开1个字符给\0实在不确定就开大点但不要太到MLE。排查RE时打印数组下标是定位越界最快的办法。5.4 int不够用变成负数乘法与累加提前换long long现象思路完全对本地小数据对大数据错。原因int最大约21亿乘法或循环累加很容易溢出成负数。解决题目数据范围到10^9量级、或结果可能超int上限时变量声明为long long输出用%lld。不要等WA了再猜哪里溢出写代码时就把类型选对。5.5 递归爆栈或调用爆炸递推代替递归现象本地测试正常交上去TLE尤其斐波那契、阶乘这类递推题。原因递归展开次数指数级增长或递归深度过大导致栈溢出。解决改成数组递推。这个习惯从这套题养起后面DP题全受益。OJ最喜欢在“看起来能递归”的题里埋大数据范围逼你学会迭代。6. 沉淀武器库AC之后别急着切题把代码拆成模板如果你从1000一路按上面的方法刷到1099手里应该已经有了一批能秒写的骨架多组输入、Case输出、字符串清理、快排比较函数、递推数组。最后这部分不讲新题讲怎么把这些骨架变成自己的武器库。6.1 三分钟复盘法AC不是结束是开始每道题AC后我习惯再花三分钟做三件事第一看刚写的代码把能复用的部分标记出来第二去题解里找一种不同思路哪怕只是while条件换种写法第三把这道题的坑写进笔记比如“这题会爆int”或“输出末尾不能有空格”。三分钟在当下是浪费时间刷到第2000题时你会庆幸有索引可查。很多人AC完就关页面同一个坑下一道题又踩一遍这才是最大浪费。6.2 个人模板库的三种素材头文件、快读、对拍脚本模板库不需要复杂三个文件足矣头文件骨架、快速读入函数、对拍脚本。比如手写一个读入整数的函数int readint(void) { int x 0; int c getchar(); while (c 0 || c 9) c getchar(); while (c 0 c 9) { x x * 10 (c - 0); c getchar(); } return x; }这段代码没有处理负数因为很多OJ题输入是正整数但使用前你必须知道这个边界。这正是模板要自己写的原因只有自己踩过坑才知道模板能处理什么、不能处理什么。把别人博客里的快读代码原样贴进自己库真出了问题连排查方向都没有。6.3 从“会做”到“吃透”用自己的话讲清楚一道题判断自己是否吃透一道题我有一个土办法不看任何笔记重写一遍再看能不能给别人讲清楚为什么这样写。重写时卡壳说明只是记住了答案没形成思路能顺畅讲清说明这道题的思维模型已经进了你的套路库。前100题真正留给你的不是一百个AC记录而是“看题面、定格式、选模板、验边界”这套流程。我后来刷其他OJ和笔试算法题靠的还是1000–1099阶段养成的习惯。你可以在本地建一个目录把练习代码分类放好每次写完新模板就更新旧的。等有一天你拿到陌生题能在半分钟内说出输入输出类型和算法方向这一百道题就没白刷。希望帮到你。本文还有配套的精品资源点击获取