一道牛逼闪闪的数学推理题

前几天在Petr的blog[墙外]上看到一道数学题Petr 本人对题目的评价是:一道测试数学推理能力的好题(A nice problem to test formal reason skills)。如果你可以熟练的进行数学推理,并有一些基础的数学背景知识,则可以解决此问题;否则,近乎不可能。胡子虽然不知道啥叫数学推理,但倒是 看过一些简单而经典的数学定理证明,所以决定尝试一下。

不过很遗憾,胡子经过接近3天断断续续的努力,仍然无法攻克此题。不过Petr在放出题目的2天后即公布了solution,胡子在这里简单翻译一下。胡子的英语不是很好,如果有翻译不当的地方,还请各位看官指正。

-----------------------------------
题目开始 -----------------------------------

题目大意如下:
   
在数轴上,你开始站在0点位置。给定两个正整数集合AB,只能交替的进行两种操作:
    1)
A集合中取一个数a,向左走a个单位距离。
    2)
B集合中取一个数b,向右走b个单位距离。
   
从行动1)开始,即先往左走。
   
问:你能够到达任意的整数点么?

   
例如:A = {15}B = {24}。要想到达-2,可以先左走5个距离,再右走4个距离,再左走1个距离,-5+4-1 = -2

   
限制:AB至多包含10000个元素,其中包含的正整数的范围为[1, 10^9]

   
题目来源:Source: SnarkNews Winter Series 2011, Round 2. (俄罗斯的一个编程比赛)

初接触题目时,这种交替走的游戏规则显然限制了我们思考的深度。很自然地,我们想到去除这个限制,那么如何去除呢?如果我们将连续的两步操作看成一步,则 我们可以构造一个新的集合 C={b-a | b属于Ba属于A},显然CZ(Z为整数集)的子集。那么,现在新的问题变为:
   
从原点出发,每次从C中取一个数走,你能够到达任意的整数点么?

接下来需要一点基础的数论知识,我们知道给定一个集合CC中所有元素的最大公约数g可被描述为
    g = q1c1 + q2c2 + ... ,
其中,q1q2...为整数   (1)

根据这个事实,再结合我们要解决的问题,我们很自然的期望:每一个被g整除的点都可以到达。公式(1)显然给我们指出了一个可以到达任意可被g整除的点的方法,但这里存在一个限制:一些qi可能是负数,而我们无法走-1次。

现在问题变为:对于C中的任意数c,我们如何走出-c如果我们可以解决这个问题,则我们可以利用公式(1)达到任意可被g整除的点。对集合C进行分类讨论:
1)
如果C中仅包含非正数,则显然无法走出 -c(这里c是负数)
2)
如果C中仅包含非负数,则显然无法走出 -c(这里c是正数)
3) C
中既包含正数也包含负数,则可以通过如下方法走出-c。假设c是正数,在C中任取一负数-d,以-d为单位向负方向走c次,再以c为单位向正方向走(d-1)次,则 -d*c + c*(d-1) = -cc是负数的情况同理可证。

也就是说,只要C中包含至少一个正数和至少一个负数,则我们可以到达点g,进而通过不断重复这个过程可以到达任意可被g整除的点。

现在,已经基本解决了新问题,让我们回到原来的问题上。直到现在,我们证明原问题的逻辑是这样:将原问题转化为新问题,由新问题可解 => 原问题可解;但却不能由原问题可解 => 新问题可解。从新旧问题的对比中我们可以看出,新问题中我们仅考虑到原问题中的偶数步可达的点,那么原问题中奇数步可达的点又对问题的解有哪些贡献呢?

依然对集合C分别讨论:
如果C是坏的 -- C或仅包含非正数或仅包含非负数。显然,偶数步不可能到达所有负数点或所有正数点,而在偶数步操作后,再采取一次操作,也仅能有限(A中元素的最大值)的扩充所能到达的点集。所以,答案依然是“NO”
如果C是好的 -- C中既包含正数也包含负数。那么通过偶数步操作可以到达任意可被g整除的点,在此基础上再进行一次操作,可以到达任意与 -a (a属于A)g同余的点。那么集合A都会产生哪些余数呢?

g = gcd(a1-b1, a2-b1, ...)   (2) 可知,g整除 a1-b1 a2-b1,则g整除它们的差,即 a1-b1 - (a2-b1) = a1-a2。同理,g整除任意的 ai-aj,所以A中任意元素模g同余。也就是说,整个A集合模g仅有一个余数,即所有奇数步可达的点集为所有模g-a1的点。

现在,我们总结一下所有可以到达的点:所有可被g整除的点(偶数步)与所有模g-a1的点(奇数步)。那么要想覆盖所有整数点,要么 g=1,要么 g=2 && a1 为奇数。对于所有 g>2 的情况,因为仅能覆盖所有余数中的0-a1,所以有很多点不可达。

好了,从理论上我们已经完美解决了该问题,但是不要忘了,本题出现在一次编程竞赛上,而每道题目是有时间要求的。按我们上述所提算法,因为AB中至多有 10^4个元素,所以集合C中可能包含多达10^8个元素,这显然是无法接受的。单单是这最后一点的小trick,也能难倒英雄汉。其实我们并不需要真正 的构造C,我们仅需知道:
1) C
中包含正数么?
2) C
中包含负数么?
3)
求得C中所有元素的最大公约数g

对于第一个问题(第二个问题类似),我们仅需查看B中的最大元素是否大于A中的最小元素即可。

对于第三个问题,需要用到上面提到的技巧。由上面的推理我们知道,g可以整除A(B中同理)中任意两个元素的差,则我们可以将C中的任意元素 ai-bj,写作 ai-bj = (ai-a1) + (a1-b1) + (b1-bj)。我们构造集合C1,由三部分数组成:a1-b1, ai-a1 for all i, b1-bj for all j,并令g1C1中所有元素的最大公约数,则容易证明 g=g1。首先,g整除g1:因为g整除C1中的所有元素,则gC1的公约数,所以g整除g1。其次,g1整除g:因为g1整除任意C中的元素ai- bj,则g1C的公约数,所以g1整除g。最终,g1=g,我们将C集合削减为C1集合,而C1集合中仅包含至多 20001 个元素。

-----------------------------------
证明结束 -----------------------------------

胡子读完了证明简直是赞叹不已,整个证明每一步都没用到什么复杂的理论知识,但每一步的推理都需要谨小慎微的进行,环环相扣。如此美妙的题目正是胡子喜欢数学的原因,逻辑严谨、触手可达而又充满挑战、惊喜不断。

与此同时,胡子也深深感到自己的不足,改天胡子会把自己半途而废无法进行下去的证明也整理出来。对比之下,看看胡子和God Petr之间巨大的差距,借此机会拿自己为例,分析一下两种不同级别的人,面对这样的数学问题,所表现出的不同思维方式。如果无法从思维方式上有所突破, 而仅仅通过练习和模仿来获取新的知识,胡子可能永远也达不到更高的高度。

保持在正确的方向上,你后续的努力才不会白白浪费,方向比努力更重要。

解题如此,其他事亦如此。 


最后,令人倍受打击的事实是:比赛开始后,God Petr在分别在第5、13、28分钟解决了E、C、A(本题对应比赛时的Problem A),也就是说他在脑中准确无误地完成上述推理的全过程并编写代码解决此题仅用时15分钟。下图是比赛结束时的board:

整场比赛的92次提交中仅有7次提交完美解决该问题,成功率相当之低:

 

 


posted on 2011-01-18 13:32  胡子拉碴的酸书生  阅读(573)  评论(0)    收藏  举报