本书从ACM-ICPC程序设计竞赛等各种程序设计竞赛的试题进行了分析和整理,并精选出典型试题进行分类解析,既可用于高校算法、程序设计课程的实验和教学,也可以用于竞赛选手的系统训练。
本书是“大学程序设计课程与竞赛训练教材”系列著作中的第2部。我们编著这一系列著作的指导思想如下。
(1)程序设计竞赛是“通过编程解决问题”的竞赛。国际大学生程序设计竞赛(International Collegiate Programming Contest,ICPC)和中学生国际信息学奥赛(International Olympiad in Informatics,IOI)在20世纪80年代中后期走向成熟,30多年来,累积了海量的试题。这些来自全球各地、凝聚了无数命题者的心血和智慧的试题,不仅可以用于程序设计竞赛选手的训练,而且可以用于教学,以系统、全面地提高学生编程解决问题的能力。
(2)我们认为,评价一个人的专业能力,要看这个人的两个方面:1)知识体系,即他能用哪些知识去解决问题,或者说,他所真正掌握并能应用的知识,而不仅仅是他学过的知识;2)思维方式,即他在面对问题(特别是不太标准化的问题)的时候,解决问题的策略是什么?对于程序设计竞赛选手所要求的知识体系,可以概括为1984年图灵奖得主Niklaus Wirth提出的著名公式“算法+数据结构=程序”,这也是计算机学科知识体系的核心部分,因此本系列的前两部著作分别是《数据结构编程实验》和《算法设计编程实验》。对于需要采用某些策略进行求解的程序设计试题,比如,不采用常用的数据结构或者需要优化解题的算法,我们进行分析整理,编写了本系列的第3部著作《程序设计解题策略》。
(3)从本质上说,程序设计是技术,所以,首先牢记学习编程要不断“Practice,Practice,Practice”!本系列选用程序设计竞赛的大量试题,以案例教学的方式进行教学实验并安排学生进行解题训练。其次,“Practice in a systematic way”。本系列的编写基于传统的教学大纲,以系统、全面地提高学生编程解决问题的能力为目标,以程序设计竞赛的试题及详细的解析、带注释的程序作为实验,在每一章的结束部分给出相关题库及解题提示,并对大部分试题给出官方的测试数据。
2013年,我们在机械工业出版社出版了《算法设计编程实验:大学程序设计课程与竞赛训练教材》。2018年,我们在CRCPress出版了该书的英文版《Algorithm Design Practice: for Collegiate Programming Contest and Education》。此外,我们还在中国台湾地区出版了繁体中文版。
吴永辉,博士,复旦大学计算机科学技术学院副教授,美国石溪大学访问学者,ICPC亚洲程序设计竞赛首训练委员会主席。他曾率队在ICPC世界总决赛上获得三枚奖牌,并应邀在阿曼、孟加拉国、马来西亚、美国的多所高校长期讲学。
王建德,信息学奥林匹克竞赛教练,国务院特殊津贴专家,中学特级教9币。他所辅导的学生曾在国际信息学竞赛(IOI)中获得7金、3银、2铜的优异成绩。他先后出版了24本关于程序设计和算法的学术专著。
前言
第1章 求解AdHoc类问题的编程实验
1.1 机理分析法的实验范例
1.2 统计分析法的实验范例
1.3 相关题库
第2章 模拟法的编程实验
2.1 直叙式模拟的实验范例
2.2 筛选法模拟的实验范例
2.3 构造法模拟的实验范例
2.4 相关题库
第3章 数论的编程实验
3.1 素数运算的实验范例
3.1.1 使用筛法生成素数
3.1.2 测试大素数
3.2 求解不定方程和同余的实验范例
3.2.1 计算最大公约数和不定方程
3.2.2 计算同余方程和同余方程组
3.2.3 计算多项式同余方程
3.3 特殊的同余式的实验范例
3.3.1 威尔逊定理和费马小定理
3.3.2 伪素数
3.3.3 欧拉定理
3.4 积性函数的实验范例
3.4.1 欧拉φ函数φ(n)
3.4.2 莫比鸟斯函数μ(n)
3.4.3 完全数和梅森素数
3.5 高斯素数的实验范例
3.6 相关题库
第4章 组合分析的编程实验
4.1 生成排列的实验范例
4.1.1 按字典序思想生成下一个排列
4.1.2 按字典序思想生成所有排列
4.2 排列组合计数的实验范例
4.2.1 一般的排列组合计数公式
4.2.2 两种特殊的排列组合计数公式
4.2.3 多重集的排列数和组合数
4.3 鸽笼原理与容斥原理的实验范例
4.3.1 利用鸽笼原理求解存在性问题
4.3.2 容斥原理应用实验
4.3.3 Ramsey定理的应用
4.4 Polya计数公式的实验范例
4.5 生成函数与递推关系的实验范例
4.5.1 幂级数型生成函数
4.5.2 指数型生成函数
4.5.3 递推关系
4.6 快速傅里叶变换的实验范例
4.7 相关题库
第5章 贪心法的编程实验
5.1 体验贪心法内涵的实验范例
5.1.1 贪心法的经典问题
5.1.2 体验贪心法内涵
5.2 利用数据有序化进行贪心选择的实验范例
5.3 在综合性的P类问题中使用贪心法的实验范例
5.4 相关题库
第6章 动态规划方法的编程实验
6.1 线性DP的实验范例
6.1.1 初步体验线性DP问题
6.1.2 子集和问题
6.1.3 最长公共子序列问题
6.1.4 最长递增子序列问题
6.2.1 背包问题
6.2.1 基本的0-1背包问题
6.2.2 完全背包
6.2.3 多重背包
6.2.4 混合背包
6.2.5 二维背包
6.2.6 分组背包
6.2.7 有依赖的背包
6.3 树形DP的实验范例
6.4 状态压缩DP的实验范例
6.5 单调优化1D/1DDP的实验范例
6.5.1 经典模型1:利用决策代价函数w的单调性优化
6.5.2 经典模型2:利用决策区间下界的单调性优化
6.5.3 经典模型3:利用最优决策点的凸性优化
6.6 相关题库
第7章 高级数据结构的编程实验
7.1 后缀数组的实验范例
7.1.1 使用倍增算法计算名次数组和后缀数组
7.1.2 计算最长公共前缀
7.1.3 后缀数组的应用
7.2 线段树的实验范例
7.2.1 线段树的基本概念和基本操作
7.2.2 线段树单点更新的维护
7.2.3 线段树子区间更新的维护
7.3 处理特殊图的实验范例
7.3.1 计算欧拉图
7.3.2 计算哈密顿图
7.3.3 计算最大独立集
7.3.4 计算割点、桥和双连通分支
7.4 相关题库
第8章 计算几何的编程实验
8.1 点线面运算的实验范例
8.1.1 计算点积和叉积
8.1.2 计算线段交
8.1.3 利用欧拉公式计算多面体
8.2 利用扫描线算法计算矩形的并的面积的实验范例
8.2.1 沿垂直方向计算矩形的并面积
8.2.2 沿水平方向计算矩形的并面积
8.3 计算半平面交的实验范例
8.3.1 计算半平面交的联机算法
8.3.2 利用极角计算半平面交的算法
8.4 计算凸包和旋转卡壳的实验范例
8.4.1 计算凸包
8.4.2 旋转卡壳实验
8.5 相关题库