正文
点击上方“
程序员小灰
”,选择“置顶公众号”
有趣有内涵的文章第一时间送达!
发出一个固定金额的红包,由若干个人来抢,需要满足哪些规则?
1.所有人抢到金额之和等于红包金额,不能超过,也不能少于。
2.每个人至少抢到一分钱。
3.要保证所有人抢到金额的几率相等。
小灰的思路是什么样呢?
每次抢到的金额 = 随机区间
( 0, 剩余金额 )
为什么这么说呢?让我们看一个栗子:
假设有10个人,红包总额100元。
第一个人的随机范围是
(0,100元)
,平均可以抢到
50元
。
假设第一个人随机到50元,那么剩余金额是100-50 = 50 元。
第二个人的随机范围是
(0, 50元)
,平均可以抢到
25元
。
假设第二个人随机到25元,那么剩余金额是50-25 = 25 元。
第三个人的随机范围是
(0, 25元)
,平均可以抢到
12.5元
。
以此类推,每一次随机范围越来越小。
方法1:二倍均值法
剩余红包金额为M,剩余人数为N,那么有如下公式:
每次抢到的金额 = 随机区间
(0, M / N X 2)
这个公式,保证了
每次随机金额的平均值是相等的
,不会因为抢红包的先后顺序而造成不公平。
举个栗子:
假设有10个人,红包总额100元。
100/10X2 = 20, 所以第一个人的随机范围是
(0,20 )
,平均可以抢到
10元
。
假设第一个人随机到10元,那么剩余金额是100-10 = 90 元。
90/9X2 = 20, 所以第二个人的随机范围同样是
(0,20 )
,平均可以抢到
10元
。
假设第二个人随机到10元,那么剩余金额是90-10 = 80 元。
80/8X2 = 20, 所以第三个人的随机范围同样是
(0,20 )
,平均可以抢到
10元
。
以此类推,每一次随机范围的均值是相等的。
//发红包算法,金额参数以分为单位
public static List<Integer> divideRedPackage(Integer totalAmount, Integer totalPeopleNum){
List<Integer> amountList = new ArrayList<Integer>();
Integer restAmount = totalAmount;
Integer restPeopleNum = totalPeopleNum;
Random random =
new Random();
for(int i=0; i1; i++){
//随机范围:[1,剩余人均金额的两倍),左闭右开
int amount = random.nextInt(restAmount / restPeopleNum * 2 - 1) + 1;
restAmount -= amount;
restPeopleNum --;
amountList.add(amount);
}
amountList.add(restAmount);
return amountList;
}
public static void main(String[] args){
List<Integer> amountList = divideRedPackage(5000, 30);
for(Integer amount : amountList){
System.out.println("抢到金额:" + new BigDecimal(amount).divide(new BigDecimal(100)));
}