知其所以然(续)

查了一下,上篇知其所以然(以学习算法为例)是08年7月写的,现在已经是10年11月,过去了两年零4个月,这说明了三件事情:1,一个问题其实你可以一直放在脑子里面,利用暗时间对其软泡硬磨,时间足够久你总会有一点新的感悟,问题其实就像那句老话说的那样,不怕贼偷就怕贼惦记,聚精会神的思考一天,也许比不上惦记一个星期(据说数学家庞加莱就特别会惦记问题)。2,事实上,当你感觉懂了的时候,你至少得反问自己一句,真的懂了吗?当你确信自己真的懂了的时候,你至少得讲给别人听,别人听懂了吗?考察你自己是否真懂了的一个很好的依据是,你是否有一种“哦,原来是这样啊,这下再也不可能忘记了”的感觉。3,我其实没有忘记这个博客。如我之前说的,记录只是学习和思考的副作用,只要还在学习和思考,就必然会有新的记录。

我有一个习惯,看定理必看证明。一个你不明白其证明的定理在我看来比不知道这个定理还要糟糕,因它给你造成一种懂了的错觉。在没有明白背后的证明之前,任何一个定理对你来说都是等价的——等价于背乘法口诀(只不过有的长一点有的短一点)。一个原本美妙的定理,把其证明扔掉就是真正的买椟还珠,暴殄天物。

从现实意义来说,去理解一个定理的证明会带来巨大的好处,首当其冲的好处就是你很难再忘掉它。这一点其实很容易解释——在理解一个定理的证明之前,定理对你而言是一堆没有内在联系的词句,而在理解了证明之后,定理就归约为证明它所需的条件加上逻辑,“逻辑”本来就存在于你的大脑里面,而证明的过程中除了公理和用到的常见定理(往往没几条)之外,宽泛地说,需要你去记的,一般来说也只有一个或两个关键的insights,也就是我们常说的证明中的神来之笔,比如几何证明里面的某条看上去莫名其妙的辅助线,一旦你知道了这条辅助线,那么整个证明就毫无难处,那么该定理的信息量便直接缩减为一条辅助线的信息量;虽然看上去这一步信息并没有缩减多少,但是如果你考虑到类似的辅助线不仅会用在这个特定的定理上,往往会在很多地方用到。很多关键的证明手法是通用的。那么其实你就是把所有以这个辅助线为关键证明手法的定理的集合的信息量归约为了这条辅助线。如果你进而甚至能够理解了作这条辅助线的思想精髓,那就更牛逼了,因为解决问题的思路更具有一般性,理解了寻找正确的辅助线的思路,你就根本不需要去记得某条特定辅助线的作法,你就把所有以作一条或几条辅助线为证明核心的定理的集合的信息量归约为了这个“寻找辅助线的思路”。

这是一个树状的知识结构,越往上层走,需要记忆的节点就越少。所谓触类旁通者,其实便是因为他擅长去理解解法背后的更具一般性的东西。所以我还有一个习惯,就是看到美妙的证明和解法总是会去一遍又一遍的去反复揣摩,试图理解想出这个证明的人到底是怎么想出来的,有没有什么一般性的方法可循,很多时候,在这样揣摩的过程中,你会理解到更深刻的东西,对问题性质更深刻的认识,对解决问题的思路更深刻的认识,这些认识不仅对于你理解当前这个定理或问题有极大的帮助,同时也有助于你解决以后会遇到的表面不同但本质一样的问题。

与看定理必看证明类似,看一个问题的解法,必然要看解法所诞生的过程,背后是否隐藏着更具一般性的解决问题的思路和原则。否则一个解法就只是一个问题的解法,跟背口诀一样。即便记住了也无法推广,即便当时记住了也容易遗忘。

举个经典的例子:每本算法书都会讲动态规划,每本讲动态规划的书都会讲背包问题,每次讲背包问题都会讲可重复背包和01背包,我们就拿《Algorithms》这本还算不错的算法书对背包问题的讲解来说吧,重复背包问题的递归公式是这样的:

K(W) = max { K(W-Wi) + Vi : Wi <= W }

这个公式的理解倒是很简单:为了把问题降阶,我们在最终的最优解里面去掉一个元素,对这个元素的可能性进行讨论,它必然是任何Vi之一(前提是Wi <= W,否则就装不下),而在去掉这个元素之后,剩下的元素肯定构成问题 K(W-Wi) 的最优解,于是递归关系出现了。

此外也可以这样来理解:要拿一组最优元素,那么总得开始一个个拿吧,对第一个拿的元素进行讨论,而问题的最优解等于讨论的各个分支的最优解中的最优者;如果拿掉Vi之后,剩下来要怎么拿才能最优呢?这就是一个 K(W-Wi) 的问题了。

01背包问题就大不一样了——每个物品都只有一件,拿掉之后就不能再拿了。我们不妨看看重复背包问题的解法是不是能用到01背包上呢?还是讨论第一个拿的元素,设被拿掉的是第i个元素,问题就归结为把剩下的物品(注意,可拿的物品少了一件)最优地装入容量为 W-Wi 的包里,所以,问题的参数便变成了两个,一个是背包剩余容量 W-Wi,另一个是剩余可拿的物品集合 S\{i} (表示去掉i之后的子集),显而易见第二个参数是物品集合的各种可能的子集,那么其可能性个数就是 2^n ,这就导致子问题的个数是 2^n, 由于要依次计算每个子问题,那么算法复杂度显然也是 2^n ,是不可接受的。

那么,《Algorithms》上又是怎么来讲解01背包问题的解法的呢?以下是原文:

Our earlier subproblems now become completely useless. We must therefore refine our concept of a subproblem to carry additional information about the items being used. We add a second parameter, 0 <= j <= n: K(W, j) = maximum value achievable using a knapsack of capacity w and items 1..j: The answer we seek is K(W, n).

首先作者说了,之前重复背包问题的解法在这里完全废掉了,所以我们必须重新定义子问题,并且子问题的条件必须要包含目前拿剩下的物品。以上这些都还不错,关键是接下来就让人吐血了。作者接着说道,我们给子问题加上一个新的参数j…

凭什么啊?

还是让我们回顾一下这样一幅经典的漫画吧:

“我们给子问题加上一个参数j”,这就像你在看数学证明时看到无比邪恶的“我们考虑…“一样,一看到这样的句子,你就知道,这个问题的证明远远不像看上去那么简单,之所以你一路看下去理解上全无困难,那完全是因为作者直接把最重要的一个insight告诉你了,举个很简单的例子,证明素数无最大,谁都会第一时间想到去反证:假设存在一个最大的素数P,那么找到比P大的素数就是证明中最关键的一步,怎么找的?一般书上是不会说的,你会看到书上这样说:假设P是最大的素数,那么我们考虑P’ = 小于等于P的所有素数的乘积+1。那么P’一来显然大于P,二来不能被小于它的所有素数整除,那么P’就成了大于P的素数。

如果你经常注意反证法,你会发现一个有趣的现象,反证法里面经常会有这样一句“我们考虑”,而“我们考虑”后面几乎肯定接着一个天外飞仙一般的insight。素数无最大这个古老的证明里面的“我们考虑”尚算是比较有迹可循的(我们想要构造一个更大的素数,而素数的等价定义就是“不能被小于它的所有素数整除,为了达到这个目的,构造的方法就较明显了)。但是有非常非常多的证明,其中关键的一步就跟嗑药磕出来做梦做出来走路跌跟头跌出来的一样(不信去翻一翻《Proofs from THE Book》),让你完全不知道他怎么想到的。

话说回来,虽然有很多数学证明的关键步骤是很难逆向工程的(因为很多时候想出那个关键步骤的本人其实也是尝试了各种方法,撞了无数堵墙,在寻求证法的尝试空间中作了N次回溯才“妙手偶得”,与其说是妙手偶得,不如说是绞尽脑汁),但并非全无章法可循,否则陶哲轩也不会写出《Solving Mathematical Problems》这样的著作来,而求解问题也就成了真正的Black Art了。

算法的解法则比精妙的数学证明稍加更容易逆向工程一点。只要你有耐心仔细地去琢磨算法的关键步骤和本质,总能从中窥探到一些更general的思想和思路来。

此外,很多经典问题,算法书上的讲法虽然时时令我们失望,但如果去网上一搜,则通常会发现更优秀的解释来。比如背包问题就是如此

简单地说,如果你对于每个问题都能真正弄清以下这几个问题的答案,那么可以肯定的是,你的理解,记忆,以及学习的效率都会得到质的提高:

  • 为什么这种解法是对的?
  • 为什么那种解法是错的?
  • 为什么这种解法不是最优的?
  • 证明为什么没有更优的解法。

回到人民群众喜闻乐见的经典例子:背包问题。为什么01背包问题的正确(高效)算法是正确(高效)的。表面的解释是,因为01背包问题的子问题定义是 K(W, j),其两个维度相乘的可能性一共有nW种,也就是说一共要计算nW个子问题,而计算每个子问题的复杂度是O(1)的。

但是如果仅仅满足于这样的解释,可以说是隔靴搔痒,并没有触及到本质。算法本质上可以看做是在一个解空间当中的搜索问题,所以要分析一个算法的好坏,首先弄清它的解空间的结构,然后分析它是怎么来探索这个解空间的。

弄清解空间的是第一步,例如排序算法,其解空间可以看做是所有可能的下标排列组合,其中有且仅有一个排列是正确的排序排列(简单起见假设元素各不相同)。那么一个算法在探索这个解空间方面的行为就决定了它的效率高低,最简单的,如果一个算法每次只能检查解空间中的一个点,那么这个算法的复杂度就是解空间的大小。对排序算法而言也就是n!。从这个角度来看,我们就会很容易的发现,所有基于比较的排序算法,其复杂度为什么是以O(nlogn)为下界的,因为一次比较操作最多有两个结果,a>b或a<b,既然只有两种结果,那么最多只能将解空间进行2分,如果每次都能完美的2分,那么找到那个唯一点最终需要的步骤就是log(n!) = O(nlogn)。如此就不难理解什么基于比较的排序算法的复杂度最好不过如此了

回到01背包问题,01背包问题的解空间其实也是类似的。一次选取就是一个01数组,其中每个元素代表其所对应的物品要不要选取。很显然,这个解空间的大小是2^n。在01背包的算法里面,每当我们解出K(W, j)(需要O(W)次计算)之后,解空间就会被折半(排除掉1/2的可能性),一共如此做n次,就能得到最终解。由于每次折半的代价是O(W),便不难理解为什么算法复杂度是O(nW)了。

那么,为什么每次计算出K(W,j)就能使解空间折半呢?那就需要来看看这个算法是如何探索解空间的,算法探索解空间的方式在其递归公式里面:

K(W, j) = max { K(W, j-1), K(W-Wj, j – 1)  + Vj }

也就是说,首先看你要不要选取第一个物品,有两种可能性(两个分支),每个分支都是一个更低阶的子问题,即在其中的任意一个分支下都要决定要不要选取第二个物品(又是两个分支),如此下递归去,可以构建出一棵有2^n方个叶子节点的树,每条从根结点到叶子节点的路径“01..101”就对应一个解,其中每个分叉代表“选”或“不选”当前的物品。

建立在对这个解空间的理解上,我们再来看为什么01背包问题的正确解法能做到O(nW)。(首先你最好将这棵树画在纸上,其中每个节点都是一个子问题K(W,j),每条分叉都是0或1。)当我们计算出所有的K(W, 1)(需要O(W)次操作)之后,我们容易注意到,所有离叶子节点的距离为1的内部节点K(W, 2)到叶子节点的两个分支都必然只能取其一了,也就是说,有一半的叶子节点被排除掉了(对解空间折半)。当我们进而计算出K(W,2)之后,同样的道理,我们容易看到,到叶子节点距离为2的内部节点的两个分支也只能取其一了,这就进而再次将解空间折半。由于每次折半需要O(W)的复杂度,所以就不难理解算法的总复杂度为O(nW)了。另一种理解的方法是,当我们计算出K(W,j)的时候,从内部节点K(W,j)到根节点的唯一路径便确定了。经过O(nW)次计算,从根节点到那个唯一解(叶子节点)的路径便完全确定了。

知道怎么做是从正确(高效)解法得到的,而知道为什么必须得那样做则往往是从错误(低效)的解法当中得到的。

然而遗憾的是,绝大多数算法书或教程都只顾一上来就告诉你正确的做法是什么,对于一些常见的错误解法,或者常见的低效解法,却根本不加分析。经验告诉我们,理解错误的做法为什么错误同样甚至更为重要,往往是在理解了错误的解法为什么错误之后,我们才能深刻的体会到为什么正确的解法是如此正确。

还是拿经典的背包问题来作例子,你几乎看不到哪本书会告诉你一个典型的低效解法为什么低效的深刻原因。我们都知道动态规划的核心在于子问题的划分,同样的问题,不同的划分办法得到的复杂度完全不一样。前面已经提到了,重复背包问题的思路在01背包问题上会带来指数级的复杂度,但是为什么呢?如果你满足于说:因为如果拿重复背包问题的思路来解01背包问题,那么子问题定义的第二个维度(物品的子集)(见前文)是指数级的,那么要计算所有子问题,当然是指数级的。那么你只是看到这个问题的表象。

如果从对解空间的探索方式来说,可以容易看出这个现象的本质,我们回顾一下01背包问题的正确(高效)算法:

K(W, j) = max { K(W, j-1), K(W-Wj, j – 1)  + Vj }

这个算法讨论的是两种情况,“要”或者“不要”选取第j个物品,这两种情况所对应的解空间是完全不交的,这就有效地将解空间划分为了不重复的两个部分。

而再来看利用重复背包问题思路的解法:

K(W, S) = max { K(W-Wi, S\{i}) + Vi : Wi <= W }

这里讨论的是首先拿掉哪一个物品,还是那句话,讨论的每一个分支都对应了算法对解空间的一个切分,我们容易看出,在“先拿物品i”和”先拿物品j“这两个分支里面,存在大量的重复,因为先拿物品i再拿j,和先拿物品j再拿i对应的是完全一样的一组选取。事实上,如果你将这个递归公式画成树状结构,会发现有n!个叶子节点。n!是什么概念?01背包问题的解空间大小本质上就只有2^n次方,穷举也不过O(2^n)的复杂度,结果这样一切分却变成了n!,可见这种对解空间的切分方法的冗余度是多么高了。你不妨看看,每一次计算K(W, S)子问题能对解空间排查多少呢?是否能像前面正确的算法那样,每次都能有效排查一半情况?理解了这一点之后,我们便注意到在划分解空间,也就是定义子问题的时候的一个原则,就是在建立递归公式的时候,尽量将解空间进行不交的切分。同时我们便有了趁手的工具去分析一个动态规划的解法的效率。

最后再举一个例子:算法书上几乎必讲的霍夫曼树。你所看的算法书在讲霍夫曼树的时候给了证明吗?讲过霍夫曼树的历史八卦吗?也许你看了霍夫曼树的构造方法之后觉得:“哦,这样啊,显然”。但是你可曾想到,在最优编码这个问题上,连香农本人之前给出的解法都只是suboptimal的,而且霍夫曼本人在得到这个算法之前也是绞尽脑汁几近放弃。如果你10分钟就“理解”了,那么百分之百只是背了课文而已。

67 Comments

  1. False_Flippy | | Reply

    路过,有人推荐给我您写的书《暗时间》正准备去买

  2. alen | | Reply

    受益了,谢谢

  3. t.k. | | Reply

    支持博主,期待更多有思想的文章。

  4. zhouleyu | | Reply

    很喜欢这种独立思考并能精彩表达的文章,好

  5. kak | | Reply

    “首当其冲”用错了

  6. Leetion | | Reply

    哎,我也很苦恼这个问题,博主有没有什么推荐算法的书籍的?

  7. 山药旦子 | | Reply

    独立的见解,大赞一个

  8. 冰火梦幻 | | Reply

    这个倒没必要。

  9. 冰火梦幻 | | Reply

    这个倒没必要。

  10. 冰火梦幻 | | Reply

    这个倒没必要。

  11. abraham | | Reply

    看到你说首当其冲我就没继续看下去了 不知道你用对了这个成语没有

    • 缪隽IR | |

      成语是用错了,不过你要是因此就没继续看,那错过了很多精彩部分

  12. rcestlavie | | Reply

    勉强看懂了定理证明但是并非自己独立思考的结果,感觉更糟糕啊。。。

  13. 陈文哲yy | | Reply

    其实做任何事情都要有个度,过犹不及,重要的是怎么把握这个度..

  14. messi--forever | | Reply

    博主写得也没错吧。如果不能被小于它的所有素数整除,那肯定不能被正整数整除啊。你倒过来想,如果一个数n可以被小于它的正整数整除,那n就一定可以被某个小于n的素数整除。因为如果那个正整数是素数,自然成立;如果那个正整数是合数,那么n肯定能被这个整数的素因数整除(合数至少有一个素因子)。

  15. imao | | Reply

    “首当其冲”的好处么?

  16. Sen Li | | Reply

    还有 而素数的等价定义就是“不能被小于它的所有素数整除。。。貌似也应该是正整数

  17. Sen Li | | Reply

    很喜欢你的博文,总是喜欢看看以前看过的看看有没有新的理解

    貌似有一个小错误。。

    那么我们考虑P’ = 小于等于P的所有素数的乘积+1
    应该是 那么我们考虑P’ = 小于等于P的>>所有正整数<<的乘积+1 吧- –

    看了半天。。。

  18. wclssdn | | Reply

    你的公式只写了出来. 没有对公式中每个字母的含义进行说明.. 菜鸟看不懂啊…

  19. Lee小漫 | | Reply

    很给力的文章啊。。呵呵

  20. ArchNew | | Reply

    现在N多的教材有一个习惯,就是N多的定理不给出证明。原因有很多,有的纯粹是作者问题,有的是篇幅问题,还有的就是这些定理的证明要用到还未介绍的知识。不过真正的好教材,前两种问题对它来说都不是问题。即便碰到最后一种问题,教材的作者也会像一个科普书的作家一样,尽量地给出直觉式的理由。遗憾的是,这样的书太少。

  21. jier-liao | | Reply

    “二来不能被小于它的所有素数整除,”可以证明p‘,是素数吗?

  22. Pencilman | | Reply

    很感谢,排序复杂度的那个分析。这样来看自己以前学算法的时候确实没有想得很深入。但我以前学习有个习惯,就是自已用的定理一定要使自己随时都能推出来的定理,但随着课程的深入我发现这样有个弊端:精力花费太大了!不断地模拟定理退出来的过程,固然可以加强自己的理解,但这样成本太大,而且有些东西根本几乎就是自己再怎么想都想不出来的啊!我们学算法当然、一定要去思考这个算法是怎么出来的,但要有个度(也许是我愚蠢的想法),我觉得更好的方式就是和大家一起来探讨这个问题,感觉这样效率会高很多。

  23. train quilt | | Reply

    看了三,再看看二吧!

  24. xRan | | Reply

    请问您的空间是哪里购买的? 速度很快,我也想购买。

  25. firo | | Reply

    pongba,《Introduction to the design and analysis of algorithms》这本书和作者对于算法的学习观点,基本上和你的一只,很给力!!最近正在拜读中,主要观点可见他的文章 Do We Teach the Right Algorithm Design Techniques ? 这是地址:http://www.csc.villanova.edu/~levitin/paper.html

    另外感谢你的文章为我学习前行的道路,指明方向。

  26. kisswind | | Reply

    公理是最重要的,对于定理没必要每个都要证明,可以当成已知。“我有一个习惯,看定理必看证明”,这样会很花时间,假如要造个汽车,你不必每个零件都了解它怎么生产的,你只需要了解每个零件的特性,使用方法。就像写程序,你不必了解每个模块的原理,只要理解它的使用方法,只要按照它定的规则使用就绝对不会有问题(前提是每个模块要像定理一样被别人证明正确了)。知识是有层级的,每一个上层的知识都建立在它的下一层级基础之上,你的应用是在哪一级的,对构成它基础的知识就没必要怀疑, 这种怀疑可以是向下没有限度的。

  27. 侯轲 | | Reply

    您好!认识你很高兴!

  28. Cross | | Reply

    哥,更新的太少了啊,所有文章都看了几遍了! 咕~~(╯﹏╰)

  29. spray gun | | Reply

    没太看明白,感觉很乱

  30. ugg boots clearance | | Reply

    很给力的文章啊。。呵呵
    祝博主新年快乐哦。

  31. 诺贝笔 | | Reply

    排序算法一直没理解透

  32. ymliu | | Reply

    知行合一。
    知识的积累固然重要,但是能否把知识转换为生产力,做出实际的贡献也是非常重要的。

  33. gordon | | Reply

    顺便说一句,从低效解法的分析得出高效解法,只限定在一类的问题内,例如局部最优问题。

    原因是人能够发挥主观能动性,在寻找道路的时候可以记录信息,从而在搜索N次以后,终于可以找到从A到B的路。

    在另外一类问题中,这种方法是无效的。

    其实得不得出解法根本不是本质,本质是你对这个问题或者说命题的本质认识,不断求解

    的过程其实就是你对信系丰富,对问题本质认识深化的过程。其实这些解法根本就是练练

    手,就像美工做个小样或者程序开发的快速原型,这里引入了一个词Enrichment——事件

    丰富,其实就是侦察一下,看看怎么回事。

    其实就是信息丰富的一个过程,对命题本质的理解要深化了。

    其实是这三个概念,事件丰富,事件关联,事件压缩。

    enrichment、correlation、deduplication

    • gordon | |

      我这都是瞎说的,一时手贱打上去了

    • miley | |

      我倒是觉得你的reply更charming一些呢

  34. LGyuan | | Reply

    读你的文章好有激情啊!

  35. InitialG | | Reply

    我晕 我的留言很2吗 怎么被删除了》?

    • 刘未鹏 | |

      不好意思,有一次误操作把这篇文章的所有留言批量删除了 🙁

  36. bigeast | | Reply

    可是现在大学课堂上一节课能将N个定理,为了赶进度完成任务,定理的证明几乎从来不讲。自己一个个看也感到力不从心。

  37. Semloh | | Reply

    正好再看算法,不错

  38. gordon | | Reply

    倒数第六行

    “为什么要知其所以然” 改为 “对已知的学习为什么要知其所以然”

    • 温海 | |

      朋友,您好!我是武汉博文视点的编辑温海。我们打算为刘未鹏出版一本书,暂定《暗时间》书名,我们现在想邀请您作为我们的读者顾问团成员,一起为这本书的内容和版式设计出谋划策。不知您是否方便?我的联系地址是wenhai.no.2@gmail.com 如果您方便的时候请跟我联系。谢谢!

  39. gordon | | Reply

    其实都是凑出来的,但是这个凑合和试错还不相同,在数学上的俚语叫两头凑,没办法当

    时我们老师就是这么教的。

    证明有从已知出发,有从结论出发,然后构造一个中间层。

    其实很多东西都是引入一个中间层的概念,数学推理过程中的很多中间公式是无法用实验

    方法实验出来的,那就是构造出来的一个中间层。

    知道做什么比知道怎么做重要的多,这就相当于老板和打工仔的关系,

    老板其实不知道怎么干,但他知道做什么,他会招来一个数学系的马仔说:

    我有一个很漂亮的证明,但是这页纸写不下了,你去把它证明一下。

    然后老板去喝酒泡miss、调情去了。理工男“哼哧哼哧”干了半天。

    提出命题和猜想的都是牛大的人,

    不过引入中间层构造命题,到最后会成圆环套圆环,恶心的跟屎一样,就需要用批判性思

    维雕出来,成为瀑布流水式的证明。数学之美从此产生,以前的证明太恶心;终于有个好

    的证明了,简捷、明快犹如一件艺术品。

    感谢陈凯歌大导演的电影,《无极》给华夏大地的语言增添了很多新元素。

    古希腊和文艺复兴时期的人一直有这么一个认知情节,不知道从哪里来的,

    每一个石头里都有一个大卫,每一个人身体里都有一个米开朗基罗,

    去掉不对,它的轮廓自然清晰的显现出来了。

    为什么要知其所以然,不知其所以然到底行不行?

    学校里成绩一直不好的同学飘过。。。

    为什么要知其所以然,

    除了归约为有限集的好处之外,还有推广的好处。

    一个技巧变成一个方法,一个方法成为一种思想,这是一种方法的推广。

    我早就对数学没什么兴趣了,倒是对数学之外的美比较有兴趣,比如美丽女教师之类的,

    当然穿上紧身裙更棒了。让那些糟老头滚蛋,但是如果糟老头穿上豹纹装,跳个草裙舞之

    类的也能接受。数学系漂亮女生不多哪能发现数学之美啊,也没兴趣知其所以然。

  40. bronze casting | | Reply

    终于见到博主更新了,围观围观

  41. Tradition | | Reply

    如同法国大餐一样值得等待和回味

  42. breaker | | Reply

    一直用Google Reader读你的文章,这次来看发现主题变了,你侧边那个“作为信息源的我”和有推荐的书籍怎么没有了?

    • 刘未鹏 | |

      不好意思,忘了加上去了。稍后加上。

    • breaker | |

      动作真快啊,我已经看到了。

  43. lele | | Reply

    等了好久。

  44. hugo | | Reply

    等了我不少时日啊 :)
    文章还是一贯的深入浅出,很有味道 :)

  45. demo_world | | Reply

    就像您说的那样..记录是学习和思考的副作用!!
    总是感觉能从您的文章中读处那么一点不一样的味道….
    所以我们更加急切希望您的最新文章,殊不知沉淀过后的思想才是你的追求。
    我们会继续支持下去,能给我们带来更多更好的思想….

    • 温海 | |

      朋友,您好!我是武汉博文视点的编辑温海。我们打算为刘未鹏出版一本书,暂定《暗时间》书名,我们现在想邀请您作为我们的读者顾问团成员,一起为这本书的内容和版式设计出谋划策。不知您是否方便?我的联系地址是wenhai.no.2@gmail.com 如果您方便的时候请跟我联系。谢谢!

  46. pengde | | Reply

    等你的文章等了好久哟

  47. Akagi201 | | Reply

    不更则已,一更惊人!

  48. Andy | | Reply

    有道无术,术可求
    有术无道,止于术
    根据文章看来,未鹏兄是领悟了数学的道,也领悟了对待科学与真理的道

  49. 小屋 | | Reply

    太好了,,我还以为再也不更新了呢

    T______T

Leave a Reply to taobaowang Cancel reply

Your email address will not be published. Required fields are marked *