【算法】【算法杂谈】已知[1,m]的等概率函数,求[1,n]的等概率函数
目录
- 前言
- 问题介绍
- 解决方案
- 代码编写
- java语言版本
- c语言版本
- c++语言版本
- 思考感悟
- 写在最后
前言
当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~
在此感谢左大神让我对算法有了新的感悟认识!
问题介绍
原问题
给定一个等概率随机1-5的函数,在不使用任何额外的随机函数下,通过rand1To5实现rand1To7函数
补充题目
给定一个以p概率产生0,1-p概率产生1的随机函数rand01P,通过该函数实现等概率的rand1To6
进阶题目
给定一个随机产生1-M的随机函数rand1ToM,请依次来实现rand1ToN的随机函数
解决方案
原问题:
1、首先求出等概率的0-4,即rand1To5()-1
2、再求出等概率的[0,5,10,15,20],即 (rand1To5()-1)* 5 (扩容)
3、此时可以求出等概率的0-24,即 (rand1To5()-1)* 5 + rand1To5()-1 (插空)
4、再mod6即可得到0~6的等概率,再+1即可得到1-7的等概率函数了!
最后公式:((rand1To5()-1)* 5 + rand1To5()-1) % 6 + 1
补充题目
1、首先需要获取一个能够出现等概率的函数,才能解决等概率的问题
2、首先0和1无法一次调用出现等概率,但是调用两次,可能的结果为 00(概率:p^2) 01(概率:p(1-p))10(概率:p(1-p)) 11((1-p) ^2),由此发现10和01的出现概率相同!利用这个即可获取一个01的等概率函数
3、如果有了等概率的01,则能通过原问题中的解法就可以求的等概率的05,也就能求出等概率的1-6了
进阶题目
1、首先将n-1转化成m进制的数
2、申请一个长度为32位的int类型数组,作为m进制的结果
3、从左向右进行等概率的获取0-(m-1)的数,也就是高位先等概率生成,如果中途发现整体数大于0了,则直接放弃,从头开始
4、最终获取到的结果再转成10进制即可
代码编写
java语言版本
原问题:
方法一:
/*** 随机返回1到5之间的数* @return*/public static int random1to5Cp1() {return (int) (Math.random() * 5 + 1);}/*** 以p的概率出现0和1* @param p* @return*/public static int randomP01Cp1(double p) {return Math.random() < p ? 0 : 1;}/*** 随机返回1到7之间的数* 要求:1、仅使用random1to5实现2、必须等概率* 方法:插空法、筛选法* @return*/public static int random1to7Cp1() {int p = 0;while ((p = (random1to5Cp1() - 1) * 5 + (random1to5Cp1() - 1)) > 20) {p = (random1to5Cp1() - 1) * 5 + (random1to5Cp1() - 1);}return (int)(p%7) + 1;}/*** 等概率实现1到6的随机函数* 要求1、仅使用randomP01Cp1实现2、等概率* @return*/public static int random1to6Cp1() {// 0-6int p = 0;while ((p = get03Cp1()*2 + (get01Cp1() + 1)) > 6) {p = get03Cp1()*2 + (get01Cp1() + 1);}return (int)(p%6) + 1;}/*** 将不等概率的变成等概率返回0和1* @return*/private static int get01Cp1() {int num1 = 0, num2 = 0;while (((num1 = randomP01Cp1(0.83)) ^ (num2 = randomP01Cp1(0.83))) != 1);return num1;}/*** 等概率获取0123* @return*/private static int get03Cp1() {return get01Cp1() * 2 + get01Cp1();}/*** 给定一个m,返回1-m等概率出现* @param m* @return*/private static int get1ToM(int m) {return (int)(Math.random() * m) + 1;}/*** 通过等概率的1-m,求等概率的1-n* @param m* @param n* @return*/private static int get1TonFromM(int m, int n) {// 首先求用m进制表示的n-1int[] mSysN = getSysMNum(n-1, m);// 产生一个小于mSysN的m进制的数int[] mSys1ToN = getSysM1ToN(mSysN, m);// 再转回到10进制return get10SysFromM(mSys1ToN, m) + 1;}/*** 从m进制转回到10进制* @param mSys1ToN* @param m* @return*/private static int get10SysFromM(int[] mSys1ToN, int m) {int index = mSys1ToN.length-1;int res = 0;while (index >= 0) {res += Math.pow(m, (mSys1ToN.length-1) - index) * mSys1ToN[index];index--;}return res;}/*** 等概率随机获取一个小于mSysN的值* @param mSysN* @param m* @return*/private static int[] getSysM1ToN(int[] mSysN, int m) {// 找到左边第一个不为0的int start = 0;while (mSysN[start] == 0) {start++;}// 生成数游标int index = start;int[] res = new int[32];// 表示上一个值是否和mSysN相等,如果相等,则这波还要继续生成,如果不相等说明已经大于了直接随机生成即可boolean isLastEquals = true;// 从高位开始随机获取while (index != mSysN.length) {// 先生成res[index] = get1ToM(m)-1;// 判断该位置的上一个是否相等if (isLastEquals) {// 相等则该位置需要比较if (res[index] > mSysN[index]) {// 说明生成的超过了,归位,全部重来index = start;isLastEquals = true;continue;}else {isLastEquals = res[index] == mSysN[index];}}// 该位置不需要比较index++;}return res;}/*** 用m进制表示value* @param value* @param m* @return*/private static int[] getSysMNum(int value, int m) {int[] res = new int[32];int mod = value;int tem = value;int index = res.length-1;while (tem != 0) {res[index--] = mod % m;tem = mod/m;mod = mod%m;}return res;}public static void main(String[] args) {int[] ints = new int[5];for (int i = 0; i < 100 ; i++ ){//System.out.println(get1TonFromM(7, 5));ints[get1TonFromM(7,5)-1] ++;//System.out.println();}CommonUtils.printArr(ints);//System.out.println(String.format("%.2f", 0.0124124124));}
c语言版本
正在学习中
c++语言版本
正在学习中
思考感悟
1、原问题主要讲述了一个思想就是如果用小范围的等概率扩容到大范围的等概率,其中先用乘法扩容,扩容不是随便扩容的,扩容的大小刚还要能够让自己插空,也就是说 0-4的等概率扩容必须是0,5,10,15,20,只有这样才能将0-4插入到空隙中形成等概率的0-24,之后通过mod来缩小范围即可
2、补充问题主要讲述了如何通过非等概率获取等概率的方法,那就是通过两次的组合发现等概率的事件来制造等概率函数
3、最后一道题看似是原问题的拓展版本,其实实现方式反而是另一种角度来看这类问题了,进阶问题其实讲述了该类问题可以通过进制方式来解决,首先将目标变成m进制,之后用0-m-1的随机来生成进制的每一位,并不断判断是否越界,直到没有越界生成一个符合的数之后返回这个数,整体上还是有序的。
写在最后
方案和代码仅提供学习和思考使用,切勿随意滥用!如有错误和不合理的地方,务必批评指正~
如果需要git源码可邮件给2260755767@qq.com
再次感谢左大神对我算法的指点迷津!
相关文章:
【算法】【算法杂谈】已知[1,m]的等概率函数,求[1,n]的等概率函数
目录 前言问题介绍解决方案代码编写java语言版本c语言版本c语言版本 思考感悟写在最后 前言 当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~ 在此感谢左大神让我对算法有了新的感悟认识! 问题介…...
【Python】Python中的列表,元组,字典
文章目录 列表创建列表获取元素修改元素添加元素查找元素删除元素列表拼接遍历列表切片操作 元组创建元组元组中的操作 字典创建字典添加/修改元素删除元素查找字典的遍历合法的key类型 列表 列表是一种批量保存数据的方式,列表使用[]表示 创建列表 创建两个空列…...
分布式系统概念和设计-分布式对象和远程调用
分布式系统概念和设计 分布式对象和远程调用 能够接收远程方法调用的对象称为远程对象,远程对象实现一个远程接口。 调用者和被调用对象分别存在不同的失败可能性,RMI和本地调用有不同的语义。 中间件 在进程和消息传递等基本构造模块之上提供编程模型的…...
11-FastDFS
一 为什么要使用分布式文件系统 单机时代 初创时期由于时间紧迫,在各种资源有限的情况下,通常就直接在项目目录下建立静态文件夹,用于用户存放项目中的文件资源。如果按不同类型再细分,可以在项目目录下再建立不同的子目录来区分…...
Word这样用,提高效率不加班
Word这样用,提高效率不加班 今天给大家分享23条Word文档的应用小技巧。对于大家来说,掌握些技巧能够效率百倍,何乐不为? 这些技巧是本人通过整理一直在用并且使用频率较高的,也希望能帮到大家。有兴趣的小伙伴可以自己…...
【Linux】调试器---gdb的使用
文章目录 一.背景知识二.安装gdb三.gdb的用法使用须知gdb的常用指令1.进入调试2.退出调试操作3.显示源代码4.设置断点breakPoint5.查看断点信息/禁用断点/开启断点/删除断点6.运行程序,开始调试run7.查看变量8.其它重要命令 一.背景知识 程序的发布方式有两种&…...
MySQL数据库之表的增删改查(进阶)
目录 1. 数据库约束1.1 约束类型1.2 NULL约束1.3 UNIQUE:唯一约束1.4 DEFAULT:默认值约束1.5 PRIMARY KEY:主键约束1.6 FOREIGN KEY:外键约束1.7 CHECK约束 2 表之间的关系2.1 一对一2.2 一对多2.3 多对多 3 新增4 查询4.1 聚合查…...
Nginx从开始到结束,简单到小白都能懂哦
绪论 大家好,很高兴能够为大家带来这篇关于Nginx配置的新手指南。在这篇博客中,我们将通过简单明了的图文教程,帮助大家快速上手Nginx配置,解锁Nginx的各种神奇功能! 一、Nginx简介 Nginx是一款功能强大的web服务器…...
Qt——Qt控件之按钮-QDialogButtonBox对话框按钮盒子控件的使用总结(例程:自定义按钮)
【系列专栏】:博主结合工作实践输出的,解决实际问题的专栏,朋友们看过来! 《项目案例分享》 《极客DIY开源分享》 《嵌入式通用开发实战》 《C++语言开发基础总结》 《从0到1学习嵌入式Linux开发》 《QT开发实战》 《Android开发实战》...
数据库学习-常用的SQL语句
背景: 汇整一下自己学习数据库过程中常见的题目及语句。 一.实例分析题 二.简单SQL查询: 1):统计每个部门员工的数目select dept,count(*) from employee group by dept;2):统计每个部门员工的数目大于一个的记录se…...
5种获取JavaScript时间戳函数的方法
5种获取JavaScript时间戳函数的方法 一、JavasCRIPT时间转时间戳方法一:Date.now()方法二:Date.parse()方法三:valueOf()方法四:getTime()方法五:Number 二、js时间戳转时间方法一:生成2022/1/18 上午10:09…...
图的宽度优先遍历
文章目录 图的宽度优先遍历程序设计程序分析图的宽度优先遍历 【问题描述】根据输入图的邻接矩阵A,给出图的宽度优先遍历序列; 【输入形式】第一行为图的结点个数n,第二行输入顶点的信息,每个顶点用一个字符表示,接下来的n行为图的邻接矩阵A。其中A[i][j]=1表示两个结点邻…...
企业AD域(域控服务器)的安装和配置详细教程
一、环境以及工具准备 软件:VMWare Workstation 2016 ( 下载链接:https://pan.baidu.com/s/1iX1VRilerYPGbGvX4pvaKw 提取码:75R6 ) 镜像:Windows Server 2016 ( 下载地址ÿ…...
面试官:一千万的数据,你是怎么查询的?
面试官:一千万的数据,你是怎么查询的? 1 先给结论 对于1千万的数据查询,主要关注分页查询过程中的性能 针对偏移量大导致查询速度慢: 先对查询的字段创建唯一索引 根据业务需求,先定位查询范围(…...
IntelliJ 上 Azure Event Hubs 全新支持来了!
大家好,欢迎来到 Java on Azure Tooling 的3月更新。在这次更新中,我们将介绍 Azure Event Hubs 支持、Azure Functions 的模板增强,以及在 IntelliJ IDEA 中部署 Azure Spring Apps 时的日志流改进。要使用这些新功能,请下载并安…...
性能测试,监控磁盘读写iostat
性能测试,监控磁盘读写iostat iostat是I/O statistics(输入/输出统计)的缩写,iostat工具将对系统的磁盘操作活动进行监视。它的特点是汇报磁盘活动统计情况,同时也会汇报出 CPU使用情况。同vmstat一样,ios…...
steam游戏搬砖项目怎么做?月入过万的steam搬砖项目教程拆解
steam游戏搬砖项目怎么做?月入过万的steam搬砖项目教程拆解 大家好,我是童话姐姐,今天继续来聊Steam搬砖项目。 Steam搬砖项目也叫CSGO搬砖项目,它并不是什么刚面世的新项目,是已经存在至少七八年的一个资深老牌项目。这个项目…...
协同运力、算力、存力,加速迈向智能世界
2023年4月20日,华为在HAS2023期间举办“迈向智能世界”主题论坛,吸引了来自全球的分析师、专家学者及媒体与会。会上,华为ICT战略与Marketing总裁彭松发表了“持续技术创新,加速迈向智能世界”的主题演讲。 华为ICT战略与Marketin…...
被裁员了,要求公司足额补缴全部公积金,一次补了二十多万!网友兴奋了,该怎么操作?...
被裁员后,能要求公司补缴公积金吗? 一位网友问: 被裁员了,要求公司把历史公积金全部足额缴纳,现在月薪2.3万,但公司每个月只给自己缴纳300元公积金,结果一次补了二十多万,一次性取出…...
家庭智能插座一Homekit智能
传统的灯泡是通过手动打开和关闭开关来工作。有时,它们可以通过声控、触控、红外等方式进行控制,或者带有调光开关,让用户调暗或调亮灯光。 智能灯泡内置有芯片和通信模块,可与手机、家庭智能助手、或其他智能硬件进行通信&#x…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...
通过MicroSip配置自己的freeswitch服务器进行调试记录
之前用docker安装的freeswitch的,启动是正常的, 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...
DBLP数据库是什么?
DBLP(Digital Bibliography & Library Project)Computer Science Bibliography是全球著名的计算机科学出版物的开放书目数据库。DBLP所收录的期刊和会议论文质量较高,数据库文献更新速度很快,很好地反映了国际计算机科学学术研…...
