编程之美:第四章 数字之趣 4.6桶中取黑白球

/*
桶中取黑白球:
有一个桶,里面有白球,黑球各有100个,人们按照以下规则把球取出来:
1每次从桶里面拿出两个球
2如果是两个同色的球,那么就放入一个黑球
3如果是两个异色的球,就再放入一个白球
问:最后桶里面只剩下一个黑球的概率是多少?

分析:
简化规模,从简单到难来找规律。先假设4个球的情况。

解法1:
假设桶里面各有2个白球和黑球。用一个set(黑球数目,白球数目)表示桶里面黑白球个数。(2,2),用第一个数来表黑球的数目,第二个数来表示白球的数目,
可以用(-2,0)表示黑球数目减少了2个,白球数目不变
定义如下关系表示对球的操作:
(a,b) + (x,y) = (a+x,b+y)
结论:
1由于每次取出两个球之后,均只会放回一个球,每次操作,桶内球的总数减1
2从桶中取出两个球之后,只可能进行如下操作: 牛逼的分析
取出两个黑球,放回一个黑球:(-2,0) + (1,0) = (-1,0) 
取出两个白球,放回一个黑球:(0,-2) + (1,0) = (1,-2)
取出一黑一白,放回一个白球:(-1,-1)  + (0,1) = (-1,0)

第一次操作之后,结果是
(1,2)
(3,0)
第二次操作之后:
(1,2) ->{(0,2)
        {(2,0)
(3,0) ->{(2,0)
第三次操作之后:
(1,2) ->{(0,2)->(1,0)
        {(2,0)->(1,0)
(3,0) ->{(2,0)->(1,0)

从推断可以看出:
1每次都会减少一个球,只剩的一个球:要么是白球,要么是黑球
2每次拿白球,要么白球数量不变,要么必然是黑球(参见-1,0),(1,-2))


解法3:
用离散横纵的异或(XOR)
两个相同的数,异或为0
    不              1
由于当球不用时,就可以放入一个黑球,那我们只能把黑球赋值1,白球赋值0
闹中想起里面装了100个1和100个0
对每次捞出的两个数字做一次异或,并将所得结果1或0丢回桶中,这样每次操作不会改变球权值的亦或值

假设黑白球各有两个,
1取出两个黑球,放回一个黑球, 0^0 = 0,剩下的结果为(1,2)
2取出一黑一白,放回一个白球, 0^1 = 1,剩下的结果为(0,2)
3最后只能取出两个白球,放回黑球, 1^1 =0,剩下的结果为(1,0)
因为异或满足结合律,即 (a ^ b) ^ c = a ^(b ^ c),操作顺序不会影响后面结果
取球的过程相当于把里面所有的求进行异或操作,也就是1 ^ 1 ^ 0 ^ 0 = 0,因此剩下一个球的时候,桶中权值等于初始时刻所有权值的亦或值,也就是0,所以剩下
的求一定是黑球

扩展:
1如果各有99个黑球和白球,那么异或值为1,必然剩下白球。每种球个数为偶数,剩下的为黑球,个数为奇数,剩下的是白球。
2如果黑白球数量不定,我们不在乎球的数量,只需要看最后异或值

输入:
100(黑球个数) 100(白球个数)
99 99 
5 6
输出:
黑球
白球
黑球
*/

#include <stdio.h>

int XOR(int iBlackNum,int iWhiteNum)
{
	int iRet = 1;//因为我们把黑球当成0,白球当成1,因此黑球不需要参加异或运算,最后的结果只与白球个数有关
	for(int i = 2 ; i <= iWhiteNum ; i++)
	{
		iRet = !iRet;
	}
	return iRet;
}

void process()
{
	int iBlackNum,iWhiteNum;
	while(EOF != scanf("%d %d",&iBlackNum,&iWhiteNum))
	{
		if(iBlackNum + iWhiteNum < 2 || iBlackNum < 0 || iWhiteNum < 0)
		{
			continue;
		}
		if(XOR(iBlackNum,iWhiteNum))//把黑球当成0,白球当成1,如果异或的结果为1,那么是白球最后剩下
		{
			printf("白球\n");
		}
		else
		{
			printf("黑球\n");
		}
	}
}

int main(int argc,char* argv[])
{
	process();
	getchar();
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值