2018考研的初试已经结束了,平时看考研群里已经有很多人在讨论在焦虑机试应该怎么复习,作为过来人在这里就随便说说自己的一些经验吧。

实现说明一下,这篇文章基本就是个扫盲,不能保证你看完文章就能从 A0变 AK,但帮助你脱离新手区,扫除对机试的恐惧,保个底让机试不会成为复试阶段的软肋还是可以的。

简单介绍

首先得先了解机试的基本情况。按照去年的考试风格,是两个小时四道题的 OJ(Online Judge)形式,也就是在线提交,在线判题返回程序在测试结果集的运行结果。AC(accept)代表正确解题,WA(Wrong Answer)表示错误答案,另外还有超时、超出内存空间等等结果。所有考试前准备的目的,就是为了更多的 AC,或者保底情况,避免 A0。

编程语言

该用什么语言

北邮 OJ 平台可以用的编程语言有三种,C(gcc4.8),C++(g++ 4.8)和 Java(注意:没有 Python,没有 JavaScript)。另外,C++是不支持 c++11的,Java 只支持到 Java6。

在这个天煞的背景下,考虑到程序时间限制(1ms)和开发速度(避免无谓的造轮子),用 C + STL 是最理想的选择。

展开来说,就是用 C 的那一套输入输出(scanf 和 printf),C 与 C++通用的循环控制、选择结构、数组等,在加上 C++独特的“宝具”——STL 标准库,来进行解题。提交的时候编译器选 g++即可。

STL 标准库内容非常多,只需要了解 Map,stack,list,queue就够了。

IDE?不存在的

两个小时做四道题对大脑转数的要求还是挺高的,更何况在那种紧张的气氛和不熟悉的开发环境之下。要保证解题能够快狠准,就需要从现在开始培养一定的针对考试的编程习惯,包括 编辑器和编译器、调试器的使用等等。

首先,抛弃手上所有的 IDE,包括但不限于 Visual Studio和 Clion,DevC++,或者只在疑难杂症的时候拿它们当单步调试的工具(但也不能依赖)。考试环境只提供了(没有智能提示的)devcpp,(长得贼丑的)CFree两种最“原始”的开发工具,也就拿来当代码高亮,保证括号补全没有基本的语法问题差不多了,很多现代 IDE、开发工具可以做的事它们一概做不了。

要适应这种艰苦恶劣的考试环境,就得从准备机试的时候开始,把开发工具换成 VScode and g++。VScode 是微软提供的跨平台编辑器,有着漂亮的界面和基本的语法高亮功能,在配置各种插件之前基本可以拿来模拟考场的开发环境,用来编辑代码,而且还能保证练习的时候是比较舒服的。

编译过程全部转到命令行用 g++完成。

调试

两个最基本额调试手段:打印大法和单步调试大法。个人推荐第一种。单步调试大法需要掌握 gdb这个 g++配套的调试工具,相对来说比较费时间(无论上手还是在考场上使用),而且比较容易出一些奇奇怪怪的问题。想成为 AK 达人的话,倒是必须掌握的。

打印大法就是在关键步骤将关键变量输出的方法,简单易行,只要注意提交之前注释掉代码就OK。

参考教材

注意到,机试是可以带任何纸质打印资料的,一本简介明了的语言参考指南显得非常重要。

抛弃所有国内教科书,包括但不限于谭浩强,除非你想拿成绩开玩笑在考试的时候验证一下int a++++会不会报错。

在这里,只推荐K&R The C Programming Language小薄本。将 ANSI C 的所有内容都讲得很透彻而简洁,里面的习题也可以作为入门练手。

能力层级

这一部分提供平时训练刷题的参考方向。列举我在去年准备的时候看过的一些题型,具体知识和代码在王道机试指南算法竞赛入门经典介绍的比较详尽。

基本输入输出

OJ 的输入输出风格可是能玩死不少人的,怎么保证循环接收输入,接收特定符号能退出,每一轮输入怎么界定,怎么输出小数点后三位浮点数,输出的时候删掉无谓信息(比如句子最后的致命空格),等等等等,都是值得关注的内容,也是首先要练习的。所幸 scanf 和 printf 函数在 KR 里面已经介绍得非常详尽,对照着看和练习就行。

数字和数组处理

数字部分有点像小学数学的找规律填数,也会夹带私货弄些奇形怪状的浮点数处理,数组处理方面典型例子就是找最大最小数,找次小数,奇偶数分离这些。一般都在签到题出现。

日期问题

闰年问题,星期几问题等等。

字符串处理

翻转字符串,回文字符串判断,甚至字符串匹配、简易正则表达式识别、字符串搜索都是有可能出现的,活用 std::string 和 char 数组的下标嗯。

模板题

图论的 D 算法 F 算法,深度优先搜索,矩阵乘法等等。这种基本都是最终 boss 级别,因为很多 ACM 资料都会有典型的算法题目,代码可以直接套用,改改关键变量就可以,所以称为模板题。

特别提名:模拟题

模拟题,可不是模拟卷子,而是一类型模拟计算机内部操作比如进程调度,死锁识别等的题目,印象最深刻就是去年最后一题算进程完成时间的。

思维方法

这里介绍一些玄学的东西,也是机试对以后的开发生涯最有帮助的东西

边界值控制和处理

刚开始接触 OJ 的时候很容易会遇到本地编译没问题,提供的测试数据也能获得预期结果可是提交之后就是 WA 这种百思不得其解的问题,根源便在于边界值考虑不周全,比如整数0,范围的边界,字符串中的空串等等,解决之道便是通过大量的练习,对每个算法题首先花上几秒考虑可能的边界情况和特殊情况,久而久之形成严密的思维。

时间性能

1ms 的时间限制,看起来非常的充分,那只是还没遇到大规模输入。在那种几万甚至十万级别的数据(OJ 上真的会有),就算是$O(n^3)$的算法,翻车也是随时随地的。

应对这个问题,得对计算机内部执行过程有最基本的认识,更好一点的得对算法的时间复杂度有认识,优化起来才不会像无头苍蝇一样。

还是祭出CSAPP,里面对程序优化的介绍比较详细,充分利用 Cache 可以编写更高效程序。

奇技淫巧

这里特别提名位运算,关键时刻可以省下大量的时间。

安利Hackers’ Delight

基本的算法设计思想

递归,动态规划,不一而足,还是那句话,需要不断的刷题积累经验。