女儿展示了一个小魔术,六张扑克牌上面写满了数字。她让我心中默默地选择一个1到60之间的任意数字x,然后她依次问我x是否在这些扑克牌中,之后她就能知道x是什么。我曾记得以前在某处看到过这个魔术。
我仔细观察这些扑克牌,寻找其中的规律。作为码农,我很快发现了左上角的数字。记得去年在上海科技馆看到有人炫耀1,2,4,8,16,...65536,那时我感到不屑。我告诉家人我也会这个魔术,甚至知道16进制的0xffffffff是4294967295,这就是职业直觉。
这个魔术很简单,对方只需知道我选择的数字x出现在哪些扑克牌上,然后将这些扑克牌左上角的数字加在一起就是x。因为1,2,4,8,16,32这六个数字的排列组合算术和可以编码从1到63的任何数字。
首先,C(6,1) + C(6,2) + C(6,3) + C(6,4) + C(6,5) + C(6,6) = 6 + 15 + 20 + 15 + 6 + 1 = 63 说明六个数字的排列组合算术和有63种可能性。其次,1,2,4,8,16,32是2的连续次幂,以2进制表示就是1,10,100,1000,10000,100000,最多只使用一次某个数字,就可以表示2进制1到111111中的任何数字,而111111正好是63。
这就是魔术的原理。如果你选的是35,而35 = 32 + 2 + 1,则只需在左上角是32,2,1的扑克上写上35即可。如果你选择的是20,而20 = 16 + 4,则只需要在左上角是16,4的扑克上写有20。
我们日常生活中都经历过类似的游戏,只是我们反着玩。给出一个数字,然后拆分成一些“基”数字的加和,尽量每个基数字只使用一次。想到是什么了吗?很简单,付钱和找零。这是一个贪心背包问题。
付钱和找零时,尽量不要同一币值的货币给多张,尽量不数钱而只将一眼看穿的币面值做累加,因此尽量每种币面只使用一次。货币面值的种类处在2进制和3进制之间,如人民币1,2(虽然现在没有了),5,10,20,50,100等面值,它们的排列组合算术运算可以表示从1元到200以内的任何元钱。
如果是卖者找零,操作也一样。货币面值的排列组合算术和,算术差对于交易双方的平衡以及货币在交易中的灵活性都有帮助。对于日常买卖的人,特别是商户而言,这些单位币值的排列组合算术和,算术差烂于心。
在现实生活中,如果我们用纸币玩魔术游戏,1元钱上会写上1元本身,以及所有与它参与组合的数字,比如3,6,8,11等。5元钱上会写上15,25,35,45等。对于5-1=4这种情况,可以在5元钱上写上4,在1元钱上旁边做个记号表示-1。
总的来说,这个游戏的迷惑性并不高。首先,对于程序员敏感的数字不应放在显眼位置,其次,其余的数字不够分散。解决这些问题的方式有很多,可以将左上角的数字多次索引找到真正的“基”数字,再混入一些其他运算。
在背后的运算面前,结果只是障眼法,逆向这些运算需要知识、技术和耐心。
本文如未解决您的问题请添加抖音号:51dongshi(抖音搜索懂视),直接咨询即可。