小玩意 - 抢红包算法(公平版 & 手速版)

简介: 小玩意 - 抢红包算法(公平版 & 手速版)


当我们在群里抢红包时真的是手速越快红包金额越大吗?

image.png

答案:当然是并不是,都说了是拼手气,岂能是拼手速!不过也可以有拼手速的方法。

20210112095826754.gif

二倍均值法(公平版)

这是一种很合理很公平的抢红包算法了,绝对不会让你拼手速的,就别天真了。

在此我们假设

红包剩余金额为 M

红包剩余数量为 N

这种算法就是每次都在区间[0,M/N×2] 随机取一个数

假设100元红包发10个人,那么合理的做法应该是每个人领到10元的概率相同。

第一个人随机金额的范围为[0,100/10×2] ,也就是[0,20],这样平均可以领到10元,此时剩余金额为100-10=90。

第二个人随机金额的范围为[0,90/9×2] ,也就是[0,20],这样平均也可以领到10元,此时剩余金额为90-10=80。

第三个人随机金额的范围为[0,80/8×2] ,也就是[0,20],这样平均也可以领到10元。

这样推导下去,每个人领到相同金额的概率应该就是相同的了。

代码

publicstaticList<Double>doubleMeanMethod(doublemoney,intnumber) {
List<Double>result=newArrayList<Double>();
if(money<0&&number<1)
returnnull;
doubleamount,sum=0;
intremainingNumber=number;
inti=1;
while(remainingNumber>1){
amount=nextDouble(0.01,2*(money/remainingNumber));
sum+=amount;
System.out.println("第"+i+"个人领取的红包金额为:"+format(amount));
money-=amount;
remainingNumber--;
result.add(amount);
i++;
    }
result.add(money);
System.out.println("第"+i+"个人领取的红包金额为:"+format(money));
sum+=money;
System.out.println("验证发出的红包总金额为:"+format(sum));
returnresult;  
}

运行结果

image.png

线段切割法(手速版)

这就是拼手速了,是时候展示手速了。

image.png

这个算法可以把总金额想象成一条线段,每个人都有机会切一刀,前面的人切剩下的后面的人再接着切,这样越是前面的人截取的长度(理解成领取到的红包金额)越大的概率就越大。

代码

publicstaticvoidlineSegmentCutting(doublemoney,intnumber) {
if(money<0&&number<1)
System.out.println("输入错误!");
doublebegin=0,end=money;
doubley=0;
for(inti=0;i<number-1;i++){
doublenn=0;
doubleamount=nextDouble(begin,end);
nn=amount-begin;
System.out.println("第"+(i+1)+"个人领取的红包金额为:"+format(nn));
y+=nn;
begin=amount;
    }
System.out.println("第"+number+"个人领取的红包金额为:"+format(end-begin));
y+=(end-begin);
System.out.println("验证发出的红包总金额为:"+format(y));
}

运行结果

image.png

完整代码

packagecom.zhl.blogTest;
importjava.util.ArrayList;
importjava.util.List;
importjava.util.Random;
importjava.util.Scanner;
publicclassredEnvelope {
/*Random 随机生成一个区间在[min , max]的数值randNumber 将被赋值为一个 MIN 和 MAX 范围内的随机数int randNumber =rand.nextInt(MAX - MIN + 1) + MIN; *//*** 生成min到max范围的浮点数**/publicstaticdoublenextDouble(finaldoublemin, finaldoublemax) {
returnmin+ ((max-min) *newRandom().nextDouble());
    }
publicstaticStringformat(doublevalue) {
returnnewjava.text.DecimalFormat("0.00").format(value); // 保留两位小数        }
// 二倍均值法publicstaticList<Double>doubleMeanMethod(doublemoney,intnumber){
List<Double>result=newArrayList<Double>();
if(money<0&&number<1)
returnnull;
doubleamount,sum=0;
intremainingNumber=number;
inti=1;
while(remainingNumber>1){
amount=nextDouble(0.01,2*(money/remainingNumber));
sum+=amount;
System.out.println("第"+i+"个人领取的红包金额为:"+format(amount));
money-=amount;
remainingNumber--;
result.add(amount);
i++;
        }
result.add(money);
System.out.println("第"+i+"个人领取的红包金额为:"+format(money));
sum+=money;
System.out.println("验证发出的红包总金额为:"+format(sum));
returnresult;
    }
// 线段切割法publicstaticvoidlineSegmentCutting(doublemoney,intnumber){
if(money<0&&number<1)
System.out.println("输入错误!");
doublebegin=0,end=money;
doubley=0;
for(inti=0;i<number-1;i++){
doublenn=0;
doubleamount=nextDouble(begin,end);
nn=amount-begin;
System.out.println("第"+(i+1)+"个人领取的红包金额为:"+format(nn));
y+=nn;
begin=amount;
        }
System.out.println("第"+number+"个人领取的红包金额为:"+format(end-begin));
y+=(end-begin);
System.out.println("验证发出的红包总金额为:"+format(y));
    }
publicstaticvoidmain(String[] args) {
Scannersc=newScanner(System.in);
System.out.println("这是一段模拟抢红包的代码。");
intnumber;
doublemoney;
System.out.print("请输入红包总金额:");
money=sc.nextDouble();
System.out.print("请输入红包数量:");
number=sc.nextInt();
//System.out.println(money + " " + number);//二倍均值法doubleMeanMethod(money,number);
//System.out.println(doubleMeanMethod(money,number).toString());//也是可以直接输出list的,为了观察方便,我就在循环中输出了,存在list里主要是为了后续方便数据的使用System.out.println();
//线段切割法lineSegmentCutting(money,number);   
    }
}
目录
相关文章
|
缓存 算法 数据管理
基于改进Slime Mold算法的多处理器公平调度
基于改进Slime Mold算法的多处理器公平调度
88 0
|
6天前
|
算法
面试场景题:如何设计一个抢红包随机算法
本文详细解析了抢红包随机算法的设计与实现,涵盖三种解法:随机分配法、二倍均值法和线段切割法。随机分配法通过逐次随机分配金额确保总额不变,但易导致两极分化;二倍均值法优化了金额分布,使每次抢到的金额更均衡;线段切割法则将总金额视为线段,通过随机切割点生成子金额,手气最佳金额可能更高。代码示例清晰,结果对比直观,为面试中类似算法题提供了全面思路。
46 15
|
7月前
|
算法 Java 程序员
抢红包必看!算法决定你的红包大小
嗨,大家好!我是小米,热爱分享的技术程序员。今天聊聊红包算法——在保证公平、随机与乐趣的同时,如何巧妙分配红包金额。主要分为线性切割法与二倍均值法。前者通过随机切割区间,后者则确保金额在一定范围内随机,使分配更均匀。两种方法各有千秋,适用于不同场合,希望能给你带来灵感!
209 0
|
机器学习/深度学习 人工智能 缓存
基于改进Slime Mold算法的多处理器公平调度
基于改进Slime Mold算法的多处理器公平调度 常州大学计算机科学与人工智能学院,常州213164 * 通信地址应为的作者。 † 这些作者对这项工作做出了同样的贡献。 算法2023,16(10),473;https://doi.org/10.3390/a16100473(注册DOI) 接收日期:2023年9月25日/修订日期:2023.10月4日/接受日期:2024.10月7日 (本文属于《可持续制造的特刊调度理论与算法》)
138 0
基于改进Slime Mold算法的多处理器公平调度
抢红包算法(公平版和手速版)
抢红包有两种算法:二倍均值法(公平版)和线段切割法(手速版)
抢红包算法(公平版和手速版)
|
算法 C# Windows
C# 实现抢红包算法
C# 实现抢红包算法
150 0
|
算法
为啥春节抢红包总不是手气最佳?看完微信抢红包算法你就明白了!
春节必不可少的活动就是抢红包啦,从以前的纸质红包到现在互联网红包(以微信红包为首),今天我们就来分析一下抢红包的算法,其中有一些是微信红包的算法,看完你就知道手气最佳是如何产生的啦!
526 0
为啥春节抢红包总不是手气最佳?看完微信抢红包算法你就明白了!
|
17天前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于生物地理算法的MLP多层感知机优化matlab仿真
本程序基于生物地理算法(BBO)优化MLP多层感知机,通过MATLAB2022A实现随机数据点的趋势预测,并输出优化收敛曲线。BBO模拟物种在地理空间上的迁移、竞争与适应过程,以优化MLP的权重和偏置参数,提升预测性能。完整程序无水印,适用于机器学习和数据预测任务。
|
7天前
|
算法 数据安全/隐私保护 异构计算
基于LSB最低有效位的音频水印嵌入提取算法FPGA实现,包含testbench和MATLAB对比
本项目展示了一种基于FPGA的音频水印算法,采用LSB(最低有效位)技术实现版权保护与数据追踪功能。使用Vivado2019.2和Matlab2022a开发,完整代码含中文注释及操作视频。算法通过修改音频采样点的最低有效位嵌入水印,人耳难以察觉变化。然而,面对滤波或压缩等攻击时,水印提取可能受影响。该项目运行效果无水印干扰,适合实时应用场景,核心逻辑简单高效,时间复杂度低。
|
7天前
|
算法 数据安全/隐私保护
基于GA遗传算法的拱桥静载试验车辆最优布载matlab仿真
本程序基于遗传算法(GA)实现拱桥静载试验车辆最优布载的MATLAB仿真,旨在自动化确定车辆位置以满足加载效率要求(0.95≤ηq≤1.05),目标是使ηq尽量接近1,同时减少车辆数量和布载耗时。程序在MATLAB 2022A版本下运行,展示了工况1至工况3的测试结果。通过优化模型,综合考虑车辆重量、位置、类型及车道占用等因素,确保桥梁关键部位承受最大荷载,从而有效评估桥梁性能。核心代码实现了迭代优化过程,并输出最优布载方案及相关参数。

热门文章

最新文章