---------------------------算法设计编程实验(第2版)---------------------------
本书是“大学程序设计课程与竞赛训练教材”系列著作中的第2部。我们编著这一系列著作的指导思想如下。
(1)程序设计竞赛是“通过编程解决问题”的竞赛。国际大学生程序设计竞赛(Inter-national 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年,我们在CRC Press出版了该书的英文版《Algorithm Design Practice: for Collegiate Programming Contest and Education》。此外,我们还在中国台湾地区出版了繁体中文版。
本书的第1版是在复旦大学程序设计集训队长期活动的基础上编写而成的,共分8章,主要内容如下:
第1章“求解Ad Hoc类问题的编程实验”:介绍了机理分析法和统计分析法,引导读者在没有经典和模式化算法可对应的情况下,学会自创简单的算法。
第2章“模拟法的编程实验”:引导读者按照题意设计数学模型的各种参数,观察变更这些参数所引起的过程状态的变化,在此基础上展开算法设计。
第3章“数论的编程实验”和第4章“组合分析的编程实验”:这两章凸显了数论和组合分析知识在算法中的应用。其中,第3章围绕初等数论中的素数运算、求解不定方程和同余方程、应用积性函数等问题展开实验。第4章介绍在编程求解组合类问题时如何计算具有某种特性的对象个数,如何将它们完全列举出来,如何使用抽屉原理解决存在性问题,如何使用容斥原理计算多个集合并的元素数,如何使用Pólya定理对一个问题的各种不同的组合状态计数。
第5章“贪心法的编程实验”和第6章“动态规划方法的编程实验”:在求解具备最优子结构特征的问题时,这两种方法是最常用、最经典的思想方法,但适用场合不同,既有相同点又有区别之处。
第7章“高级数据结构的编程实验”:选择在一般数据结构教材中没有出现但很有用的一些知识,例如后缀数组、线段树、欧拉图、哈密顿图、最大独立集、割点、桥和双连通分支等内容展开编程实验。
第8章“计算几何的编程实验”:计算几何学是算法体系中一个重要的组成部分,也是先前算法教材中最薄弱的环节。该章开展点线面运算、扫描线算法、计算半平面交、凸包计算和旋转卡壳算法等实验。
近来年,我们使用本书第1版的中、英文版在全球高校进行教学,根据读者和学生的反馈,我们对本书第1版的内容进行了修订,形成了第2版。我们除了修正第1版中的小错误,以及改进一些表述之外,还做了如下较大改进:
. 对于第3章“数论的编程实验”和第4章“组合分析的编程实验”的内容和结构,基于数论、组合数学的知识体系,进行全面的加强和改进。其中,第3章从素数运算、求解不定方程和同余方程、特殊的同余式、积性函数的应用、高斯素数5个方面展开实验;而第4章从排列的生成、排列和组合的计数、容斥原理与鸽笼原理、Pólya计数公式、生成函数与递推关系、快速傅里叶变换(FFT)6个方面展开实验。对于数论、组合分析所涉及的知识点,都采用程序设计竞赛的试题作为实验范例,也就是说,基于数论、组合分析的知识体系,实验范例“鱼鳞状”分布在各个知识点中。同时,将数学证明能力和编程解决问题能力的训练相结合,这也是数学类试题的特征。
对于第5章“贪心法的编程实验”和第6章“动态规划方法的编程实验”,则增加了经典问题的实验。在第5章中,增加了背包问题、任务调度、区间调度等经典贪心问题的实验;在第6章中,则以“背包九讲”为基础,增加0-1背包问题的实验。这样改进的目的,是使读者能够更好地体验贪心和动态规划的方法。
本书可以用于大学的算法及相关数学课程的教学和实验,也可以用于程序设计竞赛选手的系统训练。对于本书,我们的使用建议是:书中每章的实验范例可以用于算法和数学课程的教学、实验和上机作业,以及程序设计竞赛选手掌握相关知识点的入门训练;而每章最后给出的相关题库中的试题则可以作为程序设计竞赛选手的专项训练试题,以及学生进一步提高编程能力的练习题。
我们对浩如烟海的ACM-ICPC预赛和总决赛、各种大学生程序设计竞赛、在线程序设计竞赛及中学生信息学奥林匹克竞赛的试题进行了分析和整理,从中精选出314道试题作为本书的试题。其中157道试题作为实验范例试题,每道试题不仅有详尽的解析,还给出标有详细注释的参考程序;另外的157道试题为题库试题,所有试题都有清晰的提示。
本书提供了所有试题的英文原版以及大部分试题的官方测试数据和解答程序,有需要者可登录华章网站(http://www.hzbook.com)下载。
感谢Stony Brook University的Steven Skiena教授和Rezaul Chowdhury教授,Texas State University的C. Jinshong Hwang教授、Ziliang Zong教授和Hongchi Shi教授,German University of Technology in Oman的Rudolf Fleischer教授,North South University的Abul L. Haque教授和Shazzad Hosain教授,International Islamic University Malaysia的Normaziah Abdul Aziz教授,以及香港理工大学的曹建农教授,他们为本书英文版书稿的试用和改进提供了以英语为母语或官方语言的平台。感谢Georgia Institute of Technology的Jiaqi Chen同学审阅英文版书稿的部分章节。
感谢巴黎第十一大学博士生张一博同学、香港中文大学博士生王禹同学和复旦大学已故教授朱洪先生,他们对于第2版的编写提出了建设性的意见。
感谢组织程序设计训练营集训并邀请我使用本书书稿讲学的香港理工大学曹建农教授,台湾“东华大学”彭胜龙教授,西北工业大学姜学峰教授和刘君瑞教授,宁夏理工学院副校长俞经善教授,中国矿业大学毕方明教授,以及中国矿业大学徐海学院刘昆教授等。
感谢指出书稿中错误的西安电子科技大学朱微、张恩溶和中国矿业大学徐海学院贺小梅等同学。
特别感谢和我一起创建ACM-ICPC亚洲训练联盟的国内同仁,他们不仅为本书书稿,也为我的系列著作及其课程建设提供了一个实践的平台。这些年,我们并肩作战,风雨同舟,如莎士比亚《亨利五世》的台词:“今日谁与我共同浴血,他就是我的兄弟!”
由于时间和水平所限,书中肯定夹杂了一些缺点和错误,表述不当和笔误也在所难免,热忱欢迎学术界同仁和读者赐正。如果你在阅读中发现了问题,请通过电子邮件告诉我们,以便我们在课程建设和中、英文版再版时改进。我们的联系方式如下:
通信地址:上海市邯郸路220号复旦大学计算机科学技术学院吴永辉(邮编:200433)
电子邮件:yhwu@fudan.edu.cn
吴永辉王建德
2019年10月30日于上海
注:本书试题的在线测试地址如下:
在线评测系统 简称 网址
北京大学在线评测系统 POJ http://poj.org/
浙江大学在线评测系统 ZOJ http://acm.zju.edu.cn/onlinejudge/
http://zoj.pintia.cn/home
UVA在线评测系统 UVA http://uva.onlinejudge.org/
http://livearchive.onlinejudge.org/
Ural在线评测系统 Ural http://acm.timus.ru/
HDOJ在线评测系统 HDOJ http://acm.hdu.edu.cn/
---------------------------人人可懂的量子计算---------------------------
本书的目的是介绍量子计算,使得任何一个熟悉高中数学知识和愿意投入一点时间的人都能理解。我们将会学习量子比特、量子纠缠、量子隐形传态和量子算法,以及其他量子相关的主题。我们的目标不是对这些概念给出一些不明确的想法,而是使它们清晰明了。
量子计算经常出现在新闻中:中国通过隐形传态将一个量子比特从地球传送到一颗卫星上;Shor算法使我们目前的加密方法面临风险;量子密钥分发将使加密再次变得安全;Grover算法将加速数据检索。但这一切究竟意味着什么?这一切是如何运作的?所有这些都将在本书中得到解释。
不使用数学能做到这一点吗?如果我们想真正了解发生了什么,那就需要使用数学。量子力学的基本思想往往与直觉相悖。试图用文字来描述这些是行不通的,因为我们在日常生活中对它们没有经验。更糟糕的是,文字描述常常给人留下这样的印象:我们貌似理解了一些东西,而实际上我们还没有理解。好消息是,我们并不需要引入太多的数学知识。作为一名数学家,我的职责是尽可能地简化数学(坚持绝对的本质)并给出基本的例子来说明它的用法与含义。也就是说,这本书可能包含你以前从未见过的数学概念,而且和所有的数学知识一样,新的概念一开始可能看起来很奇怪。重要的是不要忽略这些例子,而且要仔细阅读计算的每一步。
量子计算是量子物理与计算机科学的完美融合,将20世纪物理学中一些最令人惊叹的观点融入一种全新的计算思维方式中。量子计算的基本单位是量子比特。我们将看到什么是量子比特以及测量量子比特时会发生什么。一个经典比特要么是0,要么是1。如果是0,我们测量它,得到0;如果是1,我们测量它,得到1。在这两种情况下,比特都保持不变。量子比特的情况则完全不同。一个量子比特可能是无限多个状态中的某一个——0和1的叠加态,但是当我们测量它时,和经典情况一样,我们只得到两个值中的一个——0或1。测量会改变量子比特,一个简单的数学模型可以精确地描述这一切。
量子比特还可能纠缠。当我们对其中一个进行测量时,会影响另一个的状态。这是我们在日常生活中没有经历过的,但我们的数学模型完美地描述了这种现象。
这三个概念——叠加、测量和纠缠——是量子力学的核心。一旦我们理解了这些概念,就能知道如何在计算中使用它们。这正体现了人类的聪明才智。
数学家通常认为:证明是美丽的,而且经常包含意想不到的见解。对于我们将要讨论的许多主题,我有完全相同的看法。贝尔定理、量子隐形传态和超密编码,这些都是珍宝。纠错线路和Grover算法更是相当惊人的。
读完本书,你应该理解了量子计算的基本概念,并会看到一些巧妙而漂亮的结构。同时,你还将认识到量子计算和经典计算并不是两个截然不同的学科。量子计算是计算的一种更基本的形式——任何经典计算机可以计算的都可以在量子计算机上计算。计算的基本单位是量子比特,而不是比特。从本质上讲,计算就是量子计算。
最后应该强调的是,本书是关于量子计算理论的介绍。它是关于软件的,而不是硬件的。虽然我们在某些地方简要地提到了硬件,偶尔也会讨论如何在物理上纠缠量子比特,但这些只是题外话。这本书讲的不是如何构建量子计算机,而是如何使用量子计算机。
以下是对这本书内容的简要描述。
第1章。经典计算的基本单位是比特。比特可以表示为处于两种可能状态之一的任何东西,标准例子是一个可以打开或关闭的电子开关。量子计算的基本单位是量子比特。这可以用电子的自旋或光子的偏振来表示,但自旋和偏振的性质对我们来说并不像开关打开或关闭那样熟悉。
我们先来看看自旋的基本性质。从奥托·斯特恩(Otto Stern)和瓦尔特·格拉赫(Walther Gerlach)的经典实验开始,他们在实验中研究了银原子的磁性。我们可以看到在不同方向上测量自旋会发生什么。测量会影响量子比特的状态。我们还会解释与测量相关的随机性。
该章的结论是,类似于自旋的实验可以用偏振滤光片和自然光来完成。
第2章。量子计算基于线性代数。幸运的是,我们只需要一小部分概念。该章介绍我们需要的线性代数知识,并说明在后面的章节中如何使用这些知识。
我们将介绍向量、矩阵、如何计算向量的长度以及如何判断两个向量是否垂直。首先介绍向量的初等运算,然后介绍矩阵是如何同时进行这些运算的。
起初这些知识的作用并不明显,但确实有用。线性代数是量子计算的基础。由于本书其余部分使用了这里介绍的数学知识,因此需要仔细阅读。
第3章。该章介绍前两章是如何联系在一起的。线性代数给出了自旋或偏振的数学模型,这使我们能够定义量子比特,并准确地描述测量时会发生什么。
接下来书中举了几个在不同方向上测量量子比特的例子。最后介绍量子密码学,并描述BB84协议。
第4章。该章描述两个量子比特纠缠的含义。使用文字很难描述纠缠,与之相对,使用数学描述则很简单。张量积是一种新的数学思想,这是将单量子比特组合成多量子比特最简单的方法。
虽然纠缠的数学描述很直观,但我们在日常生活中并不会接触到。当测量一对纠缠量子比特中的某一个时,会影响另一个。阿尔伯特·爱因斯坦(Albert Einstenin)不喜欢这种现象,并称之为“幽灵般的超距作用”。我们会看几个例子。
该章最后指出,我们不能使用纠缠来实现超光速通信。
第5章。我们看看爱因斯坦对纠缠的担忧,以及隐变量理论能否保持定域实在性。我们研究贝尔不等式的数学原理——这是一个显著的结果,它提供了一种实验方法来确定爱因斯坦的论点是否正确。虽然贝尔当时认为爱因斯坦的观点可能会被证明是正确的,但是爱因斯坦的观点是错误的。
阿图尔·埃克特(Artur Ekert)意识到,测试贝尔不等式的装置还可以用于生成密码学中使用的安全密钥,并同时测试是否存在窃听者。在该章的最后,我们描述了这种加密协议。
第6章。该章从计算的标准主题开始:比特、门和逻辑。然后简要地介绍可逆计算和爱德华·弗雷德金(Edward Fredkin)的想法。我们证明了Fredkin门和Toffoli门都是通用的——你可以仅使用Fredkin门(或Toffoli门)来构建一台完整的计算机。最后介绍Fredkin的台球计算机。尽管这并不是书中余下内容真正需要的,但它十足的独创性值得介绍。
这台计算机是由相互碰撞的球和很多墙组成的。它使人联想起粒子之间的相互作用。这激发了理查德·费曼(Richard Feynman)对量子计算的兴趣,费曼写了该领域最早的一些论文。
第7章。该章开始学习使用量子电路进行量子计算,并定义了量子门。我们将看到量子门如何作用于量子比特,并意识到我们一直在使用这种思想。我们只需要改变观点:不再认为正交矩阵作用于测量装置,而是作用于量子比特。我们还证明了一些有关超密编码、量子隐形传态、克隆和纠错的惊人结果。
第8章。这可能是最具挑战性的一章。我们会看到一些量子算法,并看到它们与经典算法相比计算的速度有多快。为了讨论算法的速度,我们需要引入复杂性理论中的思想。我们定义了查询复杂性后,就开始学习三个量子算法,并证明它们的查询复杂性比经典算法的更低。
量子算法揭示了正在解决的问题的基本结构,它不仅仅是量子并行的思想——把输入放进所有可能状态的叠加中。该章介绍了最后一部分数学知识——矩阵的Kronecker积。实际上,这部分知识的困难源于我们正在以一种全新的方式进行计算,而我们并没有使用这些新思想来解决问题的经验。
第9章。最后一章着眼于量子计算将对生活带来的影响。我们首先简要描述两个重要的算法,一个是彼得·肖(Peter Shor)发明的,另一个是洛夫·格鲁弗(Lov Grover)发明的。
Shor算法提供了一种将大数分解为质因数的方法。这似乎并不重要,但我们的互联网安全依赖于分解质因数是个难以解决的问题。能够分解大质数的乘积威胁到我们当前计算机之间的安全交易。可能还要等一段时间,我们才能拥有足够强大的量子计算机来分解目前正在使用的这些大数,但这一威胁是真实存在的,而且它已经迫使我们思考如何重新设计计算机之间的安全对话方式。
Grover算法适用于特殊类型的数据检索。我们展示了它是如何在一个小样例中工作的,并说明了它是如何在一般情况下工作的。Grover算法和Shor算法都很重要,不仅因为它们可以解决问题,还因为它们引入了新思想。这些基本思想正在被纳入新一代算法中。
学习算法之后,我们转个话题,简要地看一下如何使用量子计算来模拟量子过程。究其本质,化学就是量子力学。经典计算化学的工作原理是利用量子力学方程,并用经典计算机进行模拟。这些模拟是近似的,忽略了细节。这种方法在很多情况下都很有效,但在某些情况下就行不通了。在这种情况下,你需要这些细节,而量子计算机应该能够提供。
该章还简要地介绍了实际机器的构建。这是一个快速发展的领域,第一批机器正在出售,“云”上甚至有一台人人都可以免费使用的机器。看来我们很快就会进入量子霸权时代。(我们会解释这意味着什么。)
本书的结论是,量子计算不是一种新型的计算,而是对计算本质的发现。