忘记在哪里看到这个好玩的地方了:
Using your head is permitted
http://www.brand.site.co.il/
里面都是一些有意思的数学题。
挑其中一些翻译一下,说说自己的理解~
May 2007 riddle
“Chico和Dico是一对非常著名的魔术师。下面这个魔术常常出现在他们的节目中:
Chico首先掏出一副标准的扑克牌,一共是52张牌(大小王被他们俩吃掉了)。然后他会挑选一位观众,肯定不是托(这是个数学题)。
这位观众会从这副牌中随机选5张交给Chico,Chico会重新对它们排序。这整个过程Dico都是看不到的。
现在这位观众会按照Chico排好的顺序给Dico看前4张牌,接下来,Dico会准确地说出第五张牌是什么!”
将这个问题扩展一下,假设有n张牌,观众随机选k张牌,而Dico需要猜最后的j张牌,那么n、k、j需要满足什么样的条件才能保证这个魔术可行呢?
进一步,怎么样得到这样的策略,并且足够简单让两个魔术师学会呢?
篇外:我想起来一个同学跟我说过的魔术。他和一位搭档,叫一位观众随意告诉他搭档一件物品。当然他是不知道的。然后搭档会任意说一堆物品,每说一件他回答“是”或者“不是”,如果回答“是”那么那件物品就是观众说出来那件。他表示这个魔术甚至可以通过电话玩,当然我现在也还不知道怎么玩的。
这里要找到这样一种策略,能够按照前四张牌确定第五张牌,看起来还是比较混乱的。不过题目本身给出了一些建模的提示:
n, k, j 需要满足一些条件。
既然字母都标出来了,不妨想想它们之间的联系:一共n张牌,随机选择其中k张,然后由前(k-j)张的顺序,猜到最后的j张牌。
这样一看,还是有一些直观上能够联想到的公式:n张牌随机选k张一共是C(n,k)种选择,前k-j张的顺序一共是n*(n-1)*..*(n+j-k+1)=n!/(n+j-k)!种。
哟,那是不是需要在k-j张牌的顺序与C(n,k)种选择之间建立一种对应关系,从而能保证每次都能猜对呢?
答案正是如此。假设有n张牌,任意拿k-j张牌的排列一共是n!/(n+j-k)!种,也就是最多能有这么多种不同的编码;而随机挑选k张的组合一共是C(n,k)种。想要根据前k-j张的顺序确定整个k的组合,就必须满足C(n,k)≤n!/(n+j-k)!,也就是(n+j-k)!≤k!(n-k)!。
那么要找的映射,就是使得k-j这个排列的所有牌都在C(n,k)这k张牌中的映射。当然这样的映射应该是有很多种的。这里讲一种j=1的时候,比较简单的:
假设观众拿到的牌是a0,a1,...ak-1,并且a0 比如最后拿到cards是这样的:c0, c1, ...ck-1, 首先拿出ck-1,然后看ck-2与ck-1的大小关系。我们知道这是倒数第二次循环的时候对2取余的结果,因此如果ck-2>ck-1,则对2取余是1,倒数第二次循环的时候x=1;如果ck-2 继续看ck-3,如果ck-3最小,那么在倒数第三次循环的时候对3取余结果是0;否则是1或者2,由上面对2取余的结果x2,我们可以得到倒数第三次循环的时候x=x2 * 3 + x3。 依次往上,我们可以得到S - S%k。 不过这还不是最后要求的c0。这时候我们已知的数有k-1个,假设这k-1个数的和为Sk,未知的数为c0,那么我们知道 S = (Sk + c0) % k!, S % k = c0 在a0,a1..ak中的位置,现在我们只差S和这个位置不知道了。不过时候,我们需要尝试的数只有0到k-1,通过尝试S - S%k与这个数的组合,以及得到的这个数在a0,a1..ak中的位置进行验证,我们可以确定最后的值。 上面说了一堆,还是拿一个真实的例子来讲吧~ 看一位观众,随机抽到13,19,28,44,49。接下来Chico如何处理呢? 1. 计算S。五个数的总和是153,于是S=153%5!=33。 2. i=5, 取第33%5 = 3个数,也就是44 (从0开始数)放入卡组,此时cards={44}。将44从原卡组移除,orig变为{13,19,28,49},x变为33/5=6 3. i=4, 取第6%4 = 2个数,即28放入cards,此时cards={44,28}, orig={13,19,49}, x变为6/4=1 4. i=3, 取第1%3 = 1个数,即19放入cards,此时cards={44,28,19}, orig={13,49}, x变为1/3=0 5. i=2, 取第0%2 = 0个数,即13放入cards,此时cards={44,28,19,13}, orig={49}, x变为0/2=0 6. i=1, 将49放入cards完成,cards={44,28,19,13,49} 好的,然后Dico如何通过他们之间的默契来只看后四张牌猜第一张牌呢? 我们来客串一下Dico,并且假设我们可以一瞬间忘记44这个数字,只能看到49,13,19,28这样的排列。 1. 49, 拿过来貌似暂时没什么用,放这儿吧。cards = {49} 2. 13, 这个有用了。从cards我们可以看出来它之前应该是在第0位置的。我们推测x在除以2之前余2是0,因此此时x=0。(为什么呢,x在第一步之前本身就是0,因为它余1是0啊,0*2还是0啊...),cards={13,49} 3. 19, 观察可知19是从13和49之间拿出来的,所以可以推测x在除以3之前余3是1,因此此时x=x*3+1=1(还原与计算相反,计算的时候是先求余再除,还原需要先乘再加),cards={13,19,49} 4. 28, 同样的道理x在除以4之前余4是2,所以此时x=x*4+2=6, cards={13,19,28,49} 5. 所有数都看完啦,还有啥呢?我们还可以算一步x,虽然我们不知道x除以5之前余5多少,但是范围肯定在[x*5, x*5+4]之间,也就是[30,34]之间,所以呢S的范围是[30,34]之间,也就是原来五个数的和的范围是[150,154]之间。 6. 目前4个数的和是109,所以隐藏数的范围就是[41,45]之间。这个范围已经很小了,而且基本不需要挨个尝试了,它肯定在28与49之间,所以S余5的值是3,轻松求得S=33,隐藏数为44。 新技能get√!又可以愉快地装X了,但是要玩熟练肯定也不容易。。 不过由于才疏学浅,最后一段话没看明白!如果有人指教,就太好了~
其中cards[0]j就是最底下被遮住的牌。这样做的好处是,可以按照逆过程推测原牌的顺序!
vector