当前位置: 首页 > news >正文

用rand7()函数构造函数rand10()

题目要求:用一个已知均匀随机的rand7()(生成1~7等概率)来构造rand10()(生成1~10等概率)。

思路:题目要求用均匀分布生成另一个均匀分布。

1.前提:rand7()可以均匀生成1,2,3,4,5,6,7,目标是rand10()均匀生成1 ~ 10。

2.不能用简单的(rand7() * 10 / 7)之类的方法,因为它们不是均匀的(会偏向某些数)。

举例:

rand7()取值:1,2,3,4,5,6,7

乘以10:10,20,30,40,50,60,70

除以7:1,2,4,5,7,8,10

目标应该是1~10每个数的概率都为1/10,结果1,2,4,5,7,8,10的概率为1/7,3,6,9的概率为0,不合题意。

3.拒绝采样法:利用(rand7() - 1) * 7 + rand7()可以生成1 ~ 49之间的等概率随机数。

证明:

(1)令a = rand7() - 1,取值:0,1,2,3,4,5,6(均匀)。

(2)令b = rand7(),取值:1,2,3,4,5,6,7(均匀)。

(3)公式变成了a * 7 + b。这实际上是在构造一个两位的7进制数。

当a固定时:

a = 0:0 * 7 + b = 1 ~ 7。

a = 1:1 * 7 + b = 8 ~ 14。

a = 2: 2 * 7 + b = 15 ~ 21。

a = 3: 3 * 7 + b = 22 ~ 28。

a = 4: 4 * 7 + b = 29 ~ 35。

a = 5: 5 * 7 + b = 36 ~ 42。

a = 6: 6 * 7 + b = 43 ~ 49。

完美覆盖了1 ~ 49的所有整数。

之所以a * 7 + b这样构造是均匀的,是因为a和b是独立的随机变量,也就是两次独立的rand7()调用。概率计算:P(得到某个特定数 x) = P(a = 某值) × P(b = 某值)。实际上是在做笛卡尔积。通过(a'-1)*7 + b映射到 1~49,这是一个双射(一一对应),所以分布保持均匀。

举例:

P(得到23) = P(a=3) × P(b=2) = (1/7) × (1/7) = 1/49

任何1 ~ 49的数都能唯一表示为a * 7 + b的形式,所以每个数的概率都是1/49。

4.(rand7() - 1) * 7 + rand7()生成等概率随机数的步骤。从1 ~ 49中只取1 ~ 40的数字(映射到1 ~ 10),遇到41 ~ 49则重试。这是因为转换为rand10()的话,最大概率是将1 ~ 49分成10组,每组4个数(但49不是10的倍数),因此必须让num落在1 ~ 40范围内才有用,否则丢弃重新生成,保证1 ~ 10均匀。

附代码:

class Solution { private Random random = new Random(); // 假设提供的 rand7() 是均匀的 private int rand7() { // random.nextInt(7)是生成一个0到6之间的随机整数(包含0,不包含7) //random.nextInt(7) + 1就是生成一个1到7之间的随机整数 return random.nextInt(7) + 1; } public int rand10() { while (true) { int num = (rand7() - 1) * 7 + rand7(); // 1 ~ 49 均匀 if (num <= 40) { // 将1 ~ 40的数映射到1 ~ 10 // 如果是num % 10,那么1 % 10 + 1 = 2,映射错误,所以是(num - 1) % 10 // 要求返回1 ~ 10,而不是0 ~ 9,所以应该 + 1,不加1的映射范围是0 ~ 9 return (num - 1) % 10 + 1; // 如果 num = 41~49,则丢弃,重新生成 } } } }

ACM模式:

import java.util.Random; import java.util.Scanner; class Solution { private Random random = new Random(); // 假设提供的 rand7() 是均匀的 private int rand7() { // random.nextInt(7)是生成一个0到6之间的随机整数(包含0,不包含7) //random.nextInt(7) + 1就是生成一个1到7之间的随机整数 return random.nextInt(7) + 1; } public int rand10() { while (true) { int num = (rand7() - 1) * 7 + rand7(); // 1 ~ 49 均匀 if (num <= 40) { // 将1 ~ 40的数映射到1 ~ 10 // 如果是num % 10,那么1 % 10 + 1 = 2,映射错误,所以是(num - 1) % 10 // 要求返回1 ~ 10,而不是0 ~ 9,所以应该 + 1,不加1的映射范围是0 ~ 9 return (num - 1) % 10 + 1; // 如果 num = 41~49,则丢弃,重新生成 } } } } public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); // 需要生成多少个随机数 Solution sol = new Solution(); for (int i = 0; i < n; i++) { System.out.print(sol.rand10()); if(i < n - 1){ System.out.print(" "); } } System.out.println(); scanner.close(); } }
http://www.jsqmd.com/news/727830/

相关文章:

  • 数据血缘分析难题的Python解决方案:深度解析sqllineage技术实现
  • Hermes地缘政治市场模拟器:OSINT与预测市场的AI推演实践
  • Rusted PackFile Manager:Total War模组开发的终极指南与完整教程
  • 终极暗黑破坏神2存档修改器:Diablo Edit2完全指南
  • Android 12/13 开机广播实战:别再只用BOOT_COMPLETED了,LOCKED_BOOT_COMPLETED才是新宠
  • 国内道路护栏实力厂家排行 实测资质与产能对比 - 奔跑123
  • R语言数据报告革命已来:Tidyverse 2.0如何让金融/医疗/零售企业周报生成效率提升370%?(附Gartner验证的ROI测算模板)
  • 别再手动传Token了!SAP PI/PO REST接口OAuth 2.0自动化配置与测试全流程
  • PyTorch 2.9 里 torch.compile 为什么首个请求更慢?4 组 GPU 实验讲透冷启动、重编译与止损方案
  • 字节面试官问:“你写了Harness Engineer,那你说说它的定义和与其他概念的区别”
  • 【Dify 2026边缘部署终极指南】:3大架构陷阱、5步零故障上线、2026 Q1实测延迟压降至87ms
  • (原创)2026安卓面试复盘
  • 终极指南:5步快速安装配置foobar2000开源歌词插件foo_openlyrics
  • 国内主流草坪护栏厂家实力排行及核心优势解析 - 奔跑123
  • 怎样高效使用Adobe-GenP:完整Adobe激活工具实用指南
  • 别再只用MD5了!聊聊Java里更安全的HmacSHA1签名怎么玩(附完整代码)
  • QUIC 式丢包检测(部分)
  • 显瘦不是靠勒紧,而是版型懂你身材
  • 5步轻松搞定小红书内容批量采集:XHS-Downloader终极使用指南
  • 免费开源桌面分区管理工具NoFences:3步快速整理Windows桌面图标
  • 自增自减运算符
  • WebLaTeX零基础入门指南:5分钟搭建你的云端LaTeX写作环境
  • Illustrator批量替换神器:ReplaceItems.jsx如何让你告别重复劳动
  • 测试博文标题 at 2026-04-30
  • 办公自动化利器 !OpenClaw 完整部署教程
  • Dify日志审计能力跃迁实录(2026 LTS版深度解密):内置WAL日志快照、操作原子性追踪、AI异常聚类三大黑科技首曝
  • 图形学小白也能懂:用初中几何和Python代码,直观验证“两直线垂直斜率积为-1”
  • 从ReLU到GeLU:Transformer前馈层中的激活函数怎么选?一份基于最新研究的实践指南
  • 如何快速掌握DamaiHelper:大麦网抢票脚本完整使用指南
  • H26M78208CMR海力士闪存H26M78208CMRA