由黑球白球问题相到的

一个袋子里有100个黑球和100个白球,每次从袋子里面取出两个球扔掉,

规则如下:如果取出的两个球颜色相同则放入袋中一个黑球,不同则放入一个白球。

例如:从袋子中取出一白一黑两个球,那么则将这两个球扔掉,然后重新放回袋子中一个白球。如果取出两个白球,则放回一个黑球。

问题:最后剩余的一个球的颜色是黑色还是白色?

出自《编程之美》

思路:

1.问题抽象:

相同为黑,不同为白,您能想到某种计算机位操作吗?

异或,好吧,我没有想到。设白球为1,黑球为0,那么取球的规则就被简化为对100个0和100个1做无序的异或操作。

假如您只知道异或操作的性质想必您一定知道了答案。

不知道也没有关系

2.问题归纳简化

1)假设袋子中只有一白一黑两个球:那么1^0=1 , 即剩下一个白球

2)假设有两个白球两个黑球:1^0^1^0=0 , 0^0^1^1=0, ...,发现怎样组合都可以,你是不是想起异或操作是否满足交换律与结合率,赶紧在纸上画画,发现果然如此。

...

如果操作满足结合率和交换律,那么说明这些100个0和100个1做异或操作的顺序无论如何变都一样。

下面有两种思路,

逆向:既然可以随意组合,那么组合成这样:(0^0^...^0)[100]^(1^1^...^1)[100],很容易看出,前面括号里的一大堆0做异或操作都是0。后面的一堆1可能比较棘手。好吧,继续归纳简化:

1^1=0,

1^1^1=1,

1^1^1^1=0

...难道与奇偶有关系?奇数个1做异或都为1,偶数个则为0,能用归纳法给出证明吗?很简单,不说了

我们的问题从(0^0^...^0)[100]^(1^1^...^1)[100] 简化为 0^0=0.

好吧,给出结论:无论您手多高多牛,最后剩下的一定是“0”代表的黑球。

异或的还有一个用途:不用中间值的交换a和b的算法

void swap(int& a , int& b)

{

    a=a^b;

    b=a^b;

    a=a^b;

}

它利用了异或操作的一个性质:

a^b^b=a

a^b^a=b

posted @ 2011-03-30 12:05  樱色布  阅读(1070)  评论(5编辑  收藏  举报