两数的平方和

2010-08-28 22:29:15

Edsger Dijkstra 在他1976出版的书 The Discipline of Programming 中提出了这样一个问题:写一个函数,对于指定的n,找到所有的x和y,且 x ≥ y ≥ 0,使得 x² + y² = n;比如说,50 = 7² + 1² = 5² + 5², 48612265 = 6972² + 59² = 6971² + 132² = ……,而999没有这样的数。

Dijkstra 提出的方法可以在在一次扫描中找到所有的数,x从n的平方根开始扫描,y从0开始扫描,假设函数 B(x, y) 可以返回x和y之间所有合适的数,使用下面的规则来进行递归:

  • 如果 x² + y² < n,那么 B(x, y) = B(x, y+1),因为x总是变小,只有y变大才能得到结果。
  • 如果 x² + y² = n,那么 (x, y) 就是答案,B(x, y) = B(x-1, y+1),扫描继续。
  • 如果 x² + y² > n,那么 B(x, y) = B(x-1, y),因为y总是在变大。
  • 最后,如果 x < y,递归结束。

上面的描述可以归纳成下面的函数:

婚礼排序

2010-08-28 11:20:45

Kevin Brown 在一篇论文 Optimizing Your Wife (最优化你的妻子)里提出了一种在一群女人里用较少的约会次数找出最适合自己的妻子的方法。假设有N个女人,首先从前√N中找出“最佳的”女人,然后从剩下的女人中再找出比前√N个中“最佳”的女人更好的女人。比如说,有一百个合适的女人,和其中十个约会,然后和下一个比那十个人更好的女人结婚。你可能不会找到最合适的女人,但是你会很接近。

Eric Burnett 将上面的想法转化为了一种排序方法。首先从数组中前√N个元素中取样,找到其中最大的元素,假设为A,接着扫描后面的元素,如果一个元素比A还大,就按顺序,把这个元素和最后一个/倒数第二个/倒数第三个...元素交换,然后交换A和被交换的元素们之前的元素。在最大的元素之间重复上述过程。最后对整个数组执行插入排序,这时的排序速度将会非常快,因为绝大部分元素都接近它们最终的位置。

整个排序的复杂度是 O(n1.5) ,接近于 shell sortcomb sort

将 FILE* 变成 iostream

2010-08-16 20:48:02

unix下编程时会涉及到大量的C函数,比如从管道读取数据,或者向syslog输出错误信息,但是这些都需要使用C的stdio.h,也就是通过 FILE* 来操作数据。如此一来C++方便的 iostream 库便全无用武之地了。

为解决这个矛盾,gcc 给 iostream 提供了一个扩展,可以将 FILE* 转换成 iostream,在其文档中有简要的说明。

当然,文档中的说明太过简洁,下面是一个正式的例子。

哥德巴赫猜想

2010-08-15 23:28:13

哥德巴赫(1690-1764)是一名普鲁士数学家,和欧拉是同一年代。史上最著名的未被证明的猜想之一便是哥德巴赫猜想。其内容为,任何一个大于2的偶数都可以表示为两个质数之和,比如 28 = 5 + 23。

虽然数学家们无法证明这个猜想,但我们可以用程序来进行验证。下面的程序可以针对给定的偶数,来找到和为其的两个质数。

翻烙饼

2010-08-15 22:22:18

有个可怜的服务员:

我们饭店的厨师非常草率,每次他烤烙饼都会烙出一大堆形状不同的烙饼。因此,当我把它们送到顾客手上前,我必须在路上就把烙饼整理好,使放在上面的是最小的,底部的是最大的。我只能从顶上开始连着抓住几块烙饼,把它们全翻过来,然后一直重复下去。

这个问题是数学家的最爱,直到现在,他们仍在寻找整理好一堆烙饼所需要的最少翻烙饼次数。比尔盖茨在退学然后变成世界首富之前,曾经发表过关于这个问题的研究论文,这也是他唯一发表过的论文。