赌博问题中填空类下注的返还金额的计算方式

赌博问题中填空类下注的返还金额的计算方式

自研的一种数学方案

考虑如下问题:

赌场新研发了一种赌博方式,要求赌徒以填空方式输入一个数字,然后随机摇号生成一个标准答案,再按照所有参与下注的赌徒们输入的数字与真实值的远近(猜的准不准)分配奖金池(所有赌徒下注金额的总和),我们称这是一个填空类下注问题

那么要怎样分配,才能使得猜的越准的人赚到越多,猜的越不准的人赚的越少甚至亏钱呢? 如何才能保证赌场无需额外加钱,仅通过对奖金池的再分配实现上述效果呢(不考虑赌场抽成且要求奖金池内的钱全部分配完)?

解决方案:

设所有人下注金额的总和(即总奖池数额)为P,设任意一名(第i名)参与投注的用户的下注值为,下注金额为,标准答案为Ans

(即与标准答案的距离),所有用户当中猜的最准的(即最小的)人的下注值与Ans的差值的绝对值(即最小距离)记作,设所有相等的人构成的集合为一组,记作,当中所有人的下注金额的总和(记该组共k个人下注,第a个人下注金额为,则), n为组的数量(即总共有n组),为标准答案出现后重新分配给这个组的总积分额度,

则有(e为自然对数的底数,e≈2.718):

对于每个参与下注的人(第i个人),此人分配到的资金记为,则有(由于可能有小数,因此我们计算采用向下取整):

化成完整式子,则每个人的最终受益为:

代码实现

#python实现 class Player: def __init__(self, uid: str, invest: float, inputnum: float): self.uid = uid self.invest = invest self.inputnum = inputnum def FillBlank(playerlist: List[Player], answer: int) -> Dict[str, float]: output = {} A = {} N = {} T = {} dn = float('inf') p = 0.0 fm = 0.0 for player in playerlist: di = abs(player.inputnum - answer) A[di] = A.get(di, 0.0) + player.invest dn = min(di, dn) p += player.invest for di, val in A.items(): if dn != 0: T[di] = math.exp(-0.5 * (di - dn)) * val else: T[di] = val fm += T[di] for di, val in A.items(): N[di] = T[di] * p / fm for player in playerlist: di = abs(player.inputnum - answer) output[player.uid] = (player.invest / A[di]) * N[di] return output
//C++编写的计算函数: struct Player{ string uid; ld invest; ld inputnum; }; unordered_map<string,ld> FillBlank(vector<Player> &playerlist,ll answer){ unordered_map<string,ld> output; unordered_map<ld,ld> A; unordered_map<ld,ld> N; unordered_map<ld,ld> T;//临时变量 ld dn=INFINITY;//dmin ld p=0;//P ld fm=0;//临时变量 for(auto i:playerlist){ ld di=fabsl(i.inputnum-answer); A[di]+=i.invest; dn=min(di,dn); p+=i.invest; } for(auto i:A){ if(dn!=0)T[i.first]=exp(-0.5*(i.first-dn))*i.second; else T[i.first]=i.second; fm+=T[i.first]; } for(auto i:A){ N[i.first]=T[i.first]*p/fm; } for(auto i:playerlist){ ld di=fabsl(i.inputnum-answer); output[i.uid]=(i.invest/A[di])*N[di]; } return output; }