十四、 组合数学

人们在生活中经常会遇到排列组合问题。比如说:在 5 5 5个礼物中选 2 2 2个,问有多少种选取方法?
组合数学就是研究一个集合内满足一定规则的排列问题。这类问题如下:

  1. 存在问题:即判断这些排列是否存在
  2. 计数问题:计算出有多少种排列,并构造出来
  3. 优化问题:如果有最优解,给出最优解
    组合数学涉及的内容很多,包括:
  4. 基本计数规则:乘法规则、加法规则、生成排列组合、多项式系数、鸽巢原理等。
  5. 计数问题:二项式定理、递推关系、容斥定理、Polya定理等。
  6. 存在问题:编码、组合设计、图论中的存在问题等。
  7. 组合优化:如匹配和覆盖、图和网络的优化问题。
    这部分之讲解一些简单的类型。
鸽巢原理(抽屉原理)

内容非常简单:把 n + 1 n+1 n+1个物体放进 n n n个盒子,至少有一个盒子包含两个或更多的物体。
例如:在 1500 1500 1500人中,至少有 5 5 5人生日相同; n n n个人互相握手,一定有两个人握手的次数相同。

比如说:小A有 K K K种糖果,每种数量已知,小A不喜欢连续两次吃同样的糖果,问有没有可行的吃糖方案。
该题是非常典型的鸽巢原理问题,可以用“隔板法”求解。找出最多的一种糖果,把它的数量 N N N看成 N N N个隔板,隔成 N N N个空间(把每个隔板的右边看成一个空间);其他所有糖果的数量为 S S S

  1. 如果 S < N − 1 S<N-1 S<N1,把 S S S个糖果放到隔板之间,这 N N N个隔板不够放,必然至少有两个隔板之间没有糖果,由于这两个隔板是同一种糖果,所以无解。
  2. S ≥ N − 1 S≥N-1 SN1时,肯定有解。其中一个解是把 S S S个糖果排成一个长队,注意同种类的糖果是挨在一起的,然后每次取 N N N个糖果,按顺序一个一个地放进 N N N个空间。由于隔板的数量比每一种糖果的数量都多,所以不可能有两个同样的糖果被放进一个空间里。把 S S S个糖果放完,就是一个解,一些隔板里面可能放几种糖果。
杨辉三角和二项式定理

读者一定非常熟悉排列和组合公式。
排列: A n k = n ! ( n − k ) ! A^k_n=\displaystyle \frac{n!}{(n-k)!} Ank=(nk)!n!
组合: C n k = ( n k ) = A n k k ! = n ! k ! ( n − k ) ! C^k_n=\begin{pmatrix}n\\k \end{pmatrix}=\displaystyle \frac{A^k_n}{k!}=\displaystyle \frac{n!}{k!(n-k)!} Cnk=(nk)=k!Ank=k!(nk)!n!
这里把组合数 C n k C^k_n Cnk用符号 ( n k ) \begin{pmatrix}n\\k \end{pmatrix} (nk)表示,称为二项式系数。杨辉三角是二项式系数 ( n r ) \begin{pmatrix}n\\r\end{pmatrix} (nr)的典型应用。杨辉三角是排列成如下三角形的数字:

						    11 11 2 11 3 3 11 4 6 4 1

每一行从上一行推导而来。如果编程求杨辉三角第 n n n行的数字,可以模拟这个推导过程,逐级递推,复杂度是 O ( n 2 ) O(n²) O(n2)。不过,若改用数学公式计算,则可以直接得到结果,比用递推快多了,这个公式就是 ( 1 + x ) n (1+x)^n (1+x)n。观察 ( 1 + x ) n (1+x)^n (1+x)n的展开:
( 1 + x ) 0 = 1 (1+x)^0=1 (1+x)0=1
( 1 + x ) 1 = 1 + x (1+x)^1=1+x (1+x)1=1+x
( 1 + x ) 2 = 1 + 2 x + x 2 (1+x)^2=1+2x+x^2 (1+x)2=1+2x+x2
( 1 + x ) 3 = 1 + 3 x + 3 x 2 + x 3 1+x)^3=1+3x+3x^2+x^3 1+x)3=1+3x+3x2+x3
每行展开的系数刚好对应杨辉三角每一行的数字。即:杨辉三角可以用 ( 1 + x ) n (1+x)^n (1+x)n来定义和计算。
那么如何计算 ( 1 + x ) n (1+x)^n (1+x)n?二项式系数 ( n k ) = n ! k ! ( n − k ) ! \begin{pmatrix}n\\k \end{pmatrix}=\displaystyle \frac{n!}{k!(n-k)!} (nk)=k!(nk)!n!就是 ( 1 + x ) n (1+x)^n (1+x)n展开后的系数。它们的关系可以这样理解: ( 1 + x ) n (1+x)^n (1+x)n的第 k k k项,实际上就是从 n n n x x x中选出 k k k个,这就是组合数 ( n k ) \begin{pmatrix}n\\k \end{pmatrix} (nk)的定义。所以:
( 1 + x ) n = ∑ k = 1 n ( n k ) k n (1+x)^n=\sum_{k = 1}^{n}\begin{pmatrix}n\\k \end{pmatrix}k^n (1+x)n=k=1n(nk)kn
这个公式称为二项式定理。
有了这个公式,在求杨辉三角第n行的数字时就可以用公式直接计算了,复杂度为
O ( 1 ) O(1) O(1)。不过,该公式中有 n ! n! n!,如果直接计算 n ! n! n!,由于太大,有可能溢出。例如 n = 30 n=30 n=30 30 ! 30! 30!超过了 l o n g l o n g long\ long long long的范围。此时可以利用 ( n k − 1 ) \begin{pmatrix}n\\k-1 \end{pmatrix} (nk1) ( n k ) \begin{pmatrix}n\\{k} \end{pmatrix} (nk)的递推关系 ( n k ) ( n k − 1 ) = n − k + 1 k \displaystyle\frac{\begin{pmatrix}n\\{k} \end{pmatrix}}{\begin{pmatrix}n\\{k-1} \end{pmatrix}}=\displaystyle\frac{n-k+1}{k} (nk1)(nk)=knk+1逐个推导,避免计算阶乘。

容斥原理

在计数时,有时情况比较多,相互有重叠。为了使重叠部分不被重复计算,可以这样处理:先不考虑重叠的情况,把所有对象的数目计算出来,然后减去重复计算的数目。这种计数方法称为容斥原理。例如一根长为 60 m 60m 60m的绳子,每隔 3 m 3m 3m做一个记号,每隔 4 m 4m 4m也做一个记号,然后把有记号的地方剪断,问绳子共被剪成了多少段?
容斥原理的解题思路是:

  1. 3 3 3的倍数有 20 20 20个,不算绳子两头,有: 20 − 1 = 19 20-1=19 201=19个记号;
  2. 4 4 4的倍数有 15 15 15个;
  3. 既是 3 3 3的倍数又是 4 4 4的倍数的,有: 60 ÷ ( 3 × 4 ) = 5 60÷(3×4)=5 60÷(3×4)=5个。
  4. 所以记号的总数量是: ( 20 − 1 ) + ( 15 − 1 ) − ( 5 − 1 ) = 29 (20-1)+(15-1)-(5-1)=29 (201)+(151)(51)=29,绳子被剪成 29 29 29段。

概率与期望

概率和数学期望是概率论和统计学中的数学概念。
设有随机变量 X X X,出现取值 x i x_i xi的概率是 p i p_i pi,把它们的乘积之和称为数学期望(均值),记为 E ( X ) : E(X): E(X):
E ( X ) = ∑ i = 1 n x i p i E(X)=\sum_{i = 1}^{n}x_ip_i E(X)=i=1nxipi

E ( X ) E(X) E(X)是基本的数学特征之一,它反映了随机变量平均值的大小。
以妇女的生育率为例,假设某国有 2000 2000 2000万个育龄妇女,不生育妇女有 277 277 277万,一孩 724 724 724万,二孩 883 883 883万,三孩 116 116 116万。记一个妇女的孩子数量是 X X X,取值 0 、 1 、 2 、 3 0、1、2、3 0123,概率分别是: 277 / 2000 = 0.1385 、 724 / 2000 = 0.362 、 883 / 2000 = 0.4415 、 116 / 2000 = 0.058 277/2000=0.1385、724/2000=0.362、883/2000=0.4415、116/2000=0.058 277/2000=0.1385724/2000=0.362883/2000=0.4415116/2000=0.058。那么平均每个妇女生育的孩子数量如下:
E ( X ) = 0 × 0.1385 + 1 × 0.362 + 2 × 0.4415 + 3 × 0.058 = 1.419 E(X)=0×0.1385+1×0.362+2×0.4415+3×0.058=1.419 E(X)=0×0.1385+1×0.362+2×0.4415+3×0.058=1.419
数学期望具有线性性质。有限个随机变量之和的数学期望等于每个变量的数学期望之和: E ( X + Y ) = E ( X ) + E ( Y ) E(X+Y)=E(X)+E(Y) E(X+Y)=E(X)+E(Y)
竞赛中求数学期望的题目一般都会用到它的线性性质。由于线性性质和DP的状态转移思想很相似,所以常常用DP来实现。

例如:一个软件有 S S S个子系统,会产生 n n n b u g bug bug。现在要找出所有种类的 b u g bug bug。假设某人一天发现一个 b u g bug bug。一个 b u g bug bug属于某个子系统的概率是 1 S \displaystyle \frac{1}{S} S1,属于某种分类的概率是 1 n \displaystyle \frac{1}{n} n1,问发现 n n n b u g bug bug,且每个子系统都发现 b u g bug bug的天数的期望。 0 < n , s ≤ 1000 0<n,s≤1000 0<n,s1000。给出 n 和 s n和s ns,求出数学期望。
分析
定义状态 d p [ i ] [ j ] dp[i][j] dp[i][j],它表示已经找到 i i i b u g bug bug,并存在于 j j j个子系统中,要达到目标状态还需要的期望天数。其中, d p [ n ] [ s ] dp[n][s] dp[n][s]表示已经找到 n n n b u g bug bug,且存在于 s s s个子系统,说明已经达到了目标,还需要 0 0 0天,所以 d p [ n ] [ s ] = 0 dp[n][s]=0 dp[n][s]=0。从 d p [ n ] [ s ] dp[n][s] dp[n][s]倒推回 d p [ 0 ] [ 0 ] dp[0][0] dp[0][0],就是本题的答案,即还没有找到任何 b u g bug bug的情况下到达 d p [ n ] [ s ] dp[n][s] dp[n][s]时需要的期望天数。
d p [ i ] [ j ] dp[i][j] dp[i][j]开始:后面 1 1 1天找到 1 1 1 b u g bug bug,可能有以下 4 4 4种情况:

  1. d p [ i ] [ j ] dp[i][j] dp[i][j]:发现一个 b u g bug bug,属于已经有的 i i i个分类和 j j j个系统,概率为 p 1 = ( i / n ) ∗ ( j / s ) p1=(i/n)*(j/s) p1=(i/n)(j/s)。这一天相当于浪费了。
  2. d p [ i + 1 ] [ j ] dp[i+1][j] dp[i+1][j]:发现一个 b u g bug bug,不属于已有分类、属于已有系统,概率为:
    p 2 = ( 1 − i / n ) ∗ ( j / s ) p2=(1-i/n)*(j/s) p2=(1i/n)(j/s)
  3. d p [ i ] [ j + 1 ] dp[i][j+1] dp[i][j+1]:发现一个 b u g bug bug,属于已有分类、不属于已有系统,概率为:
    p 3 = ( i / n ) ∗ ( 1 − j / s ) p3=(i/n)*(1-j/s) p3=(i/n)(1j/s)
  4. d p [ i + 1 ] [ j + 1 ] dp[i+1][j+1] dp[i+1][j+1]:发现一个 b u g bug bug,不属于已有系统、不属于已有分类,概率为: p 4 = ( 1 — i / n ) ∗ ( 1 − j / s ) p4=(1—i/n)*(1-j/s) p4=(1—i/n)(1j/s)

可以验证: p 1 + p 2 + p 3 + p 4 = 1 p1+p2+p3+p4=1 p1+p2+p3+p4=1
状态转移方程如下:
d p [ i ] [ j ] = p 1 ∗ d p [ i ] [ j ] + p 2 ∗ d p [ i + 1 ] [ j ] + p 3 ∗ d p [ i ] [ j + 1 ] + p 4 ∗ d p [ i + 1 ] [ j + 1 ] + 1 dp[i][j]=p1*dp[i][j]+p2*dp[i+1][j]+p3*dp[i][j+1]+p4*dp[i+1][j+1]+1 dp[i][j]=p1dp[i][j]+p2dp[i+1][j]+p3dp[i][j+1]+p4dp[i+1][j+1]+1
+ 1 +1 +1是因为末尾要加上 1 1 1

整理得到:
d p [ i ] [ i ] = ( p 2 ∗ d p [ i + 1 ] [ i ] + p 3 ∗ d p [ i ] [ j + 1 ] + p 4 ∗ d p [ i + 1 ] [ j + 1 ] + 1 ) / ( 1 − p 1 ) dp[i][i]=(p2*dp[i+1][i]+p3*dp[i][j+1]+p4*dp[i+1][j+1]+1)/(1-p1) dp[i][i]=(p2dp[i+1][i]+p3dp[i][j+1]+p4dp[i+1][j+1]+1)/(1p1)
= ( n ∗ s + ( n i ) ∗ j ∗ d p [ i + 1 ] [ j ] + i ∗ ( s − j ) ∗ d p [ i ] [ j + 1 ] =(n*s+(ni)*j*dp[i+1][j]+i*(s-j)*dp[i][j+1] =(ns+(ni)jdp[i+1][j]+i(sj)dp[i][j+1]
+ ( n − i ) ∗ ( s − j ) ∗ [ i + 1 ] [ j + 1 ] ) / ( n ∗ s − i ∗ j ) +(n-i)*(s-j)*[i+1][j+1])/(n*s-i*j) +(ni)(sj)[i+1][j+1])/(nsij)
在写程序时,从 d p [ n ] [ s ] dp[n][s] dp[n][s]倒推到 d p [ 0 ] [ 0 ] dp[0][0] dp[0][0] d p [ 0 ] [ 0 ] dp[0][0] dp[0][0]就是答案。

    cin >> n >> s;for (int i = n; i >= 0; i--) {for (int j = s; j >= 0; j--) {if (i == n && j == s) {dp[n][s] = 0.0;} else {dp[i][j] = (n * s + (n - i) * j * dp[i + 1][j] + i * (s - j) * dp[i][j + 1] +(n - i) * (s - j) * dp[i + 1][j + 1]) / (n * s - i * j);}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/29775.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java中的封装、继承和多态的概念是什么?

封装 封装是面向对象编程的一个核心概念&#xff0c;它涉及到隐藏对象的属性和实现细节&#xff0c;只对外公开接口&#xff0c;控制在程序中属性的读和修改的访问级别。封装的目的是增强安全性和简化编程&#xff0c;使用者不必了解具体的实现细节&#xff0c;而只是要通过外…

当同时绑定mousedown和mouseup时,不执行mouseup

问题描述&#xff1a; 当我同时给一个标签添加mousedown和mouseup两个鼠标事件&#xff0c;点击span的时候会触发mousedown事件&#xff0c;但是不会执行mouseup事件&#xff1b;但是注释图二中的setCloudControl方法又能触发mouseup。 后来查阅资料&#xff0c;发现是在封装a…

[算法刷题积累] 两数之和以及进阶引用

两数之和很经典&#xff0c;通常对于首先想到的就是暴力的求解&#xff0c;当然这没有问题&#xff0c;但是我们如果想要追求更优秀算法&#xff0c;就需要去实现更加简便的复杂度。 这里就要提到我们的哈希表法: 我们可以使用unordered_map去实现&#xff0c;也可以根据题目&a…

【Gradio】Chatbots 如何用 Gradio 创建聊天机器人

Creating A Chatbot Fast 简介 聊天机器人是大型语言模型的一个流行应用。使用 gradio &#xff0c;您可以轻松构建您的聊天机器人模型的演示&#xff0c;并与您的用户分享&#xff0c;或者使用直观的聊天机器人用户界面自己尝试。 本教程使用 gr.ChatInterface() &#xff0c;…

Lua优化技巧

常见的Lua优化小技巧 Lua常见优化点&#xff1a;1. 尽量使用局部变量2. table的相关减少对表的访问for循环预分配表空间元表 3. string的相关4. 避免运行时加载编译5. 尽量避免频繁创建临时对象闭包表 Lua常见优化点&#xff1a; 1. 尽量使用局部变量 尽量将变量局部化&#x…

SiGILP是什么?

SiGILP是什么&#xff1f; SiGILP&#xff08;Simultaneous Generative and Interpretive Language Processing&#xff0c;中文&#xff1a;同时生成和解释语言处理&#xff09;是一种先进的多模态模型。简单来说&#xff0c;SiGILP可以同时理解和生成多模态数据&#xff0c;…

SpringMVC系列四: Rest-优雅的url请求风格

Rest请求 &#x1f49e;Rest基本介绍&#x1f49e;Rest风格的url-完成增删改查需求说明代码实现HiddenHttpMethodFilter机制注意事项和细节 &#x1f49e;课后作业 上一讲, 我们学习的是SpringMVC系列三: Postman(接口测试工具) 现在打开springmvc项目 &#x1f49e;Rest基本介…

基于Spark3.3.4版本,实现Standalone 模式高可用集群部署

目录 一、环境描述 二、部署Spark 节点 2.1 下载资源包 2.2 解压 2.3 配置 2.3.1 配置环境变量 2.3.2 修改workers配置文件 2.3.3 修改spark.env.sh文件 2.3.4 修改spark-defaults.conf 2.4 分发 2.5 启动服务 2.5.1 启动zookeeper 2.5.2 启动hdfs 2.5.3 启动spar…

归并排序 (递归实+非递归)

前言 归并排序是一种逻辑很简单&#xff0c;但是实现有点难度的排序&#xff0c;尤其是非递归&#xff0c;对于区间的把握更是需要一点逻辑的推导&#xff0c;但是没有关系&#xff0c;轻松拿捏 归并排序gif 归并排序单趟实现 1&#xff0c;创建tmp数组&#xff0c; 2&#xff…

javaWeb项目-在线考试系统详细功能介绍

项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboot、SSM、vue、MYSQL、MAVEN 数据库工具&#xff1a;Navicat、SQLyog 1、Java简介 Java语…

「Qt Widget中文示例指南」如何实现一个滑动条(一)

Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写&#xff0c;所有平台无差别运行&#xff0c;更提供了几乎所有开发过程中需要用到的工具。如今&#xff0c;Qt已被运用于超过70个行业、数千家企业&#xff0c;支持数百万设备及应用。 滑动条示例展示了如…

轻轻松松上手的LangChain学习说明书

本文为笔者学习LangChain时对官方文档以及一系列资料进行一些总结&#xff5e;覆盖对Langchain的核心六大模块的理解与核心使用方法&#xff0c;全文篇幅较长&#xff0c;共计50000字&#xff0c;可先码住辅助用于学习Langchain。 一、Langchain是什么&#xff1f; 如今各类AI…

昇思25天学习打卡营第1天|快速入门

学AI还能赢奖品&#xff1f;每天30分钟&#xff0c;25天打通AI任督二脉 (qq.com) 本节通过MindSpore的API来快速实现一个简单的深度学习模型。若想要深入了解MindSpore的使用方法&#xff0c;请参阅各节最后提供的参考链接。 import mindspore from mindspore import nn from …

项目训练营第一天

项目训练营第一天 springboot后端环境搭建 1、首先需要找文章下载好tomcat、JDK、maven、mysql、IDEA。&#xff08;软件下载及环境变量配置略&#xff09; 2、在下载好的IDEA中&#xff0c;选择新建spring initial项目&#xff0c;选定java web&#xff0c;即可新建一个spri…

从Manifest V2到V3:Chrome扩展后台脚本不完全指南,background.js的运行机制

背景 最近我在接触Chrome插件开发&#xff0c;发现后台脚本&#xff08;background script&#xff09;非常有趣。在开发过程中&#xff0c;我思考了关于这个脚本的三个问题&#xff0c;希望大家也能分享一下见解&#xff1a; background.js 在什么时候运行&#xff1f;backg…

模块的加载机制

模块的加载机制是编程中一个重要的概念&#xff0c;它涉及到在运行时将模块&#xff08;可以是独立的源代码文件或预编译的二进制文件&#xff09;引入到程序中的过程。 模块查找&#xff1a; 加载机制首先会根据程序中引用的模块名称进行查找。在Node.js中&#xff0c;对于自…

win11 之下载安装 allure

1. 下载 https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/2.25.0/allure-commandline-2.25.0.zip 2. 配置系统变量 path 下添加解压后的bin目录 3. 验证是否安装成功 输入 allure

element ui 封装Table组件

1.首先npm i element-ui -S 安装element-ui 2.引入 Element 在 main.js 中写入以下内容&#xff1a; import Vue from vue; import ElementUI from element-ui; import element-ui/lib/theme-chalk/index.css; import App from ./App.vue; Vue.use(ElementUI); new Vue({ el…

Mac 安装HomeBrew(亲测成功)

1、终端安装命令&#xff1a; /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"执行后&#xff0c;没有安装git&#xff0c;会先安装&#xff0c;安装后再执行一下命令。 2、根据中文选择源安装 3、相关命令 查看版本号&a…

python flask使用flask_migrate管理数据库迁移

&#x1f308;所属专栏&#xff1a;【Flask】✨作者主页&#xff1a; Mr.Zwq✔️个人简介&#xff1a;一个正在努力学技术的Python领域创作者&#xff0c;擅长爬虫&#xff0c;逆向&#xff0c;全栈方向&#xff0c;专注基础和实战分享&#xff0c;欢迎咨询&#xff01; 您的点…