发出一个固定金额的红包,由若干人来抢,需要满足哪些规则?
1.所有人抢到金额之和等于红包金额,不能超过,也不能少于。
2.每个人至少抢到一分钱。
3.要保证所有人抢到金额的几率相等。
一般想到的是每次抢红包的时候直接随机就好,随机的上限是剩余的红包余额。
每次抢到的金额 = 随机区间(0,剩余金额)
但是这样是有问题的。先抢的人会有很大的优势,越往后的人随机的金额越小
例:
假设有10个人,红包总额100元。
第一个人的随机范围(0,100元),平均可以抢到50元。
假设第一人随机到50元,剩余金额是100-50 = 50元。
第二个人的随机范围是(0,50元),平均可以抢到25元。
以此类推,每一次随机范围越来越小。
二倍均值法
剩余红包金额为M,剩余人数为N,那么有如下公式:
每次抢到的金额 = 随机区间(0,M/N X 2)
这个公式 ,保证了每次随机金额的平均值是相等的,不会因为抢红包的先后顺序而造成不公平。
例:
假设有10个人,红包总额100元。
(100 / 20 )x 2 = 20 所以第一个人的随机范围是(0,20 ),平均可以抢到10元。
假设第一个人随机到10元,那么剩余金额是100-10 = 90 元。
90/9X2 = 20, 所以第二个人的随机范围同样是(0,20 ),平均可以抢到10元。
假设第二个人随机到10元,那么剩余金额是90-10 = 80 元。
80/8X2 = 20, 所以第三个人的随机范围同样是(0,20 ),平均可以抢到10元。
以此类推,每一次随机范围的均值是相等的。
import java.util.*;
public class WeiXinRedPackage1 {
public static void main(String[] args) {
double sum = 0;
ArrayList<Double> res
= WXRedPackageAlgorithm(10,3);
for(double money:res) {
sum += money;
System.out.print(money +" ");
}
System.out.println();
System.out.println(sum);
}
private static ArrayList<Double> WXRedPackageAlgorithm(double restMoney,int restNum){
ArrayList<Double> res
= new ArrayList<>(restNum);
Random random=new Random();
while(restNum>1) {
//最大的红包为:两倍的平均红包大小
double max=(restMoney/restNum) * 2;
//产生[0,1)之间的随机数
double r=random.nextDouble();
//抢到的红包区间[0,max)
double money = r * max;
if(money<0.01)
money = 0.01;
else
money= Math.floor(money*100)/100;
res.add(money);
restNum--;
restMoney -= money;
}
//最后一个红包为剩余余额
res.add(Math.floor(restMoney*100)/100 );
return res;
}
}
#!user/bin/env python
#-*- coding utf-8 -*-
# author:liruikun
import random
# summoney=input("please input the amount of money:")
# divide_n=input("divide into?:")
def hongbao(money,n):
k=n
sum=0#sum为前n个人抢得的总和,为了方便计算最后一个人的金额,初始值为0
round=n#剩余人次
while k>1:
current_money = money # 当前剩余的钱,初始值为money
for i in range(1,n+1):
get_money=random.randint(0,int(2*current_money/round))
print('id[%s] have geted money %s'%(i,get_money))
current_money -= get_money
round -= 1
sum += get_money
k-=1
if k==1:#最后一个人,分得剩余的所有
print('id[%s] have geted money %s'%(n,money-sum))
print(current_money)
hongbao(100,10)