神奇的异或运算

http://hi.baidu.com/llydmissile/item/a0556ad9def0923e48e1ddba


话说周一某实验室有16名同学,有一天*老师把大家叫到一起说:下周来做实验的时候,我会给你们每个人背后贴一张纸,纸上的数字从1到16都有可能,不同 同学背后的数字可以重复。你们每个人可以看到别人背上的数字,但不能看到自己的数字。贴纸之后你们之间不允许进行任何形式的沟通交流。之后你们排队依次来 D***,告诉我你自己背后的数字是多少;由于D***室隔音效果很好,室外的人不能听到室内的同学的说话声(更好的说法是,每个人独自在一张小纸条上写 下猜测结果,这就避免了可能由排队猜数的时间和顺序带来的“交流”)。等到16名同学都猜完之后公布结果。只要你们16个人中间能有一个人猜对自己背后的 数字,我会让大家都得满分;但如果你们都没有猜对自己背后的数字的话,则你们全部都要重修有机实验。那么你要怎样做才能避免挂科的命运呢? 
这是一道很有趣的谜题。刚看到时觉得这是根本不可能的事情,只能蒙了。后来经高人matrix67点拨,才发现并了解了这个很奇妙的解法。 
c语言的排序问题中,如果要交换两个变量的值,我们常常要引入一个temp的临时变量。如果不引入这个变量,这个问题该怎么实现呢?这是我想出来的一种解法。 
a=a+b; 
b=a-b; 
a=a-b; 
我觉得很神奇,因为这用运算没有牺牲任何空间就完成了两个变量数值的交换,不知道是不是很火星。今天又看到了另一种解法,更神奇。这种解法用到了异或运算。 
这是数的异或运算规则 :0^0=0;   0^1=1;   1^0=1;   1^1=0 简单地说,就是两个量一样就是0,不一样就是1. 
而十进制数的异或运算就是先转成二进制,再计算。 
a=9 b=11我们通过异或运算来实现a b值的交换。 
a = a^b = 1001^1011= 0010 
b = a^b = 0010^1011 = 1001 = 9 
a = a^b = 0010^1001 = 1011 = 11 
异或运算还有其他的一些性质。 
如果a = b^c^d 
则 d = a^b^c 
a^b^b=a 

有了这些知识,现在给出上面问题的答案。 
为了叙述的简便,我们把数字1到16简单地替换为0到15。游戏前,大家按某种顺序给所有人从0到15依次编号。游戏开始后,每个人把自己能看到的15个数与自己的编号一起异或起来,在猜数时报出这个异或的结果。这个方案能保证总有一个人恰好报出自己的数。 
假 设这16个数异或起来的结果为X(显然0 ≤ X ≤ 15),第i个人身上的数记为A_i,那么他猜的数其实就是X xor A_i xor i。因为根据上面的知识X xor A_i就是出除自己外另外15个人背上数的异或值,那么,编号为X的人(此时i=X)报出的数恰好就是他背上的那个数。对于数字1到16的情况,只需要在 计算前后减一加一即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值