前段时间看到了一则微信红包赌博群的广告,公布的规则如下:
- 10元发4包,互相抢,抢到金额最小的需要接龙(再发一个10元的红包,就这么接龙下去),如果群主金额最小,则倒数第二人接龙,如果出现多个数值一样,则猜拳接龙
- 如果抢到了固定金钱,则可以叫群主返现,具体规则对应如下:
抽红包金额 | 反现金额 | 抽红包金额 | 反现金额 |
---|---|---|---|
1.11 | 11.1 | 1.23 | 12.3 |
2.22 | 13.33 | 4.44 | 15.55 |
3.33 | 22.2 | 2.34 | 23.4 |
4.56 | 16.66 | 5.67 | 18.88 |
7.77 | 40 | 6.78 | 40 |
8.88 | 88.8 | 7.89 | 40 |
下面来求一下玩家赢钱的期望
基本思路
微信红包实现机制模拟
微信红包的金钱分配机制未知,假设其实现方式如下:
- 把钱的单位由元转换为分,如上述10元,变成1000分
- 把这1000分看成1000个一条线上的球,其中有999个间隙,用3个隔板随机填入这999个间隙中,这样就把1000个球分成4份,总共
有种组合,可以证明,每一份的期望都是250
- 由于抢到的期望是一样的,因此可以假设第一份是玩家1的(这里仅考虑玩家抢到红包的情况),由于群主大概率有外挂能抢到,假设第二份是群主的,第3份,第4份分别是玩家2和玩家3的
方便起见,先忽略掉规则2,来算一下玩家1的期望
期望计算
假设玩家1所分到的金钱为i,而在这个前提下收入的期望为,不难得出期望的计算公式为:
下面计算:
当玩家1得到的金钱为i时,总共的组合数为(第一个隔板确定放在第i个间隙上,而它其余的隔板都不能房子其左边的间隙上)
由于群主一定拿到红包,实际上就是取另外3个人最小值进行红包接龙,最极端的条件是群主只拿到1分钱,剩下999分分摊给其他3人,当玩家当时,玩家1绝对不会输钱,这个时候总共有
种组合,此时期望为
当i<334时,这个时候玩家1可能需要接龙,这个时候,其余两个玩家分配的金钱至少为i。这个时候,又分如下3种情况
玩家2和玩家3的钱都比玩家1多
这个时候可以作如下思路的转换:
- 在1000个球中取
个球出来,平均分配于3个玩家
-
两个隔板填入剩下
个球的间隙中,第1份是群主的,第2份和第3份分别分别为玩家2和玩家3的,这样,确保了玩家1一定会需要接龙。
因此可知,这种情况总共有种,发生概率为:
其余两个玩家中其中一个玩家的钱跟第一个玩家一样,另一个玩家的金钱比这两个玩家要多
这个时候,玩家1有一半概率需要接龙。
假设是玩家2的金钱与玩家1相等,算出的结果乘以2即可,作如下思路的转换
- 在1000个球中取
个球出来,平均分配于3个玩家
-
一个隔板填入剩下
个球的间隙中,第1份是群主的,第2份为玩家3的。确保玩家3的钱大于其余两个玩家。
因此可知,这种情况总共有种,发生概率为:
3个玩家的金钱都一样
这个时候只有1种可能,玩家1有1/3的概率需要接龙,发生的概率为:
一定不需要接龙的情况
分析了上面3种情况之后,最后就是一定不需要接龙的可能,其概率为:
接龙的话,赢钱为i-1000,可以求出期望为:
当然,除了接龙之外,还有抽到特定金额就赢钱的情况,这个时候在作特殊处理即可。
将所有的E[i]求和即可得到赢钱的期望,需要注意的是由于其余3人至少获得1分,所以i最大为997
代码实现(swift)
func combinations(_ top:Int,bottom:Int)->Int{
var res = 1
for i in 1...top{
res *= bottom + 1 - i
res /= i
}
return res
}
let maxCount = combinations(3, bottom: 999)
var validCount = 0
var Expectation = 0.0
for i in 1...997{
var money = Double(i)
switch i{
case 111:
money += 1110
case 123:
money += 1230
case 222:
money += 1333
case 234:
money += 2340
case 333:
money += 2220
case 456:
money += 1666
case 567:
money += 1888
case 678:
money += 4000
case 777:
money += 4000
case 789:
money += 4000
case 888:
money += 8880
default:
break
}
if(i>=334){
Expectation += money*Double(combinations(2, bottom: 999-i))/Double(maxCount)
continue
}
let loseCount = Double(combinations(2,bottom:999 - i*3))
let oneVSOneCount = Double(999 - i*3)*2
let oneVSOneVSOneCount = 1.0
let loseRate = loseCount/Double(maxCount)
let oneVSOneRate = oneVSOneCount/Double(maxCount)
let oneVSOneVSOneRate = oneVSOneVSOneCount/Double(maxCount)
let winRate = (Double(combinations(2, bottom: 999-i)) - loseCount - oneVSOneCount - oneVSOneVSOneCount)/Double(maxCount)
Expectation += loseRate*(money-1000)+winRate*money + 1.0/2*oneVSOneRate*money + 1.0/2*oneVSOneRate*(money-1000) + 1.0/3*oneVSOneVSOneRate*(money-1000) + 2.0/3*oneVSOneVSOneRate*money
}
print("E=\(Expectation)" )
运行结果
最后的结果为E = -63.09,也就是说玩家1平均每抢一次红包都会损失0.63元
如果忽略规则2(即把switch这段代码注释掉),则最后的结果为E = -0.8333,即,由此可以看出上述求解过程还是有优化的空间的。
网友评论