├── # 8.2 求解线性递推关系2.md ├── .gitignore ├── 10.1 图和图模型.md ├── 10.4 连通性.md ├── 10.4 连通性:结论.md ├── 10.5 欧拉通路与哈密顿通路.md ├── 10.6 最短通路问题.md ├── 10.7 平面图.md ├── 10.8 图着色.md ├── 11.1 树的概述:基础定义.md ├── 11.1 树的概述:树的性质.md ├── 11.2 树的应用:前缀码.md ├── 11.3 树的遍历.md ├── 11.3 树的遍历:相关代码.md ├── 11.4 树的应用:n皇后问题.md ├── 11.4 生成树.md ├── 11.5 最小生成树.md ├── 12.1 布尔函数.md ├── 12.2 布尔函数的表示.md ├── 12.4 电路的极小化.md ├── 13.1 语言和文法.md ├── 13.2 带输出的有限状态机.md ├── 4.4 求解同余方程.md ├── 4.4 求解同余方程2.md ├── 4.6 密码学.md ├── 5.1 数学归纳法.md ├── 5.2 强归纳法和良序性.md ├── 5.3 递归定义与结构归纳法.md ├── 5.4 递归算法.md ├── 5.5 程序正确性.md ├── 6.1 计数的基础.md ├── 6.2 鸽巢原理.md ├── 6.3 排列与组合.md ├── 6.4 二项式系数和恒等式.md ├── 6.5 排列与组合的推广.md ├── 7.1 离散概率引论.md ├── 7.2 概率论.md ├── 7.3 贝叶斯定理.md ├── 7.4 期望值和方差.md ├── 8.1 递推关系的应用.md ├── 8.2 求解线性递推关系.md ├── 8.3 分治算法和递推关系.md ├── 8.5 容斥.md ├── 8.6 容斥原理的应用.md ├── 9.1 关系及其性质.md ├── 9.3 关系的表示.md ├── 9.4 关系的闭包.md ├── 9.5 等价关系.md ├── 9.6 偏序.md ├── Code ├── .idea │ ├── .gitignore │ ├── Code.iml │ ├── modules.xml │ ├── php.xml │ └── vcs.xml ├── BFS.php ├── BFS2.php ├── Cache │ └── temp.json ├── DFS.php ├── DFS:n皇后问题.php ├── FileCache.php ├── debug.php ├── debug2.php ├── result.log ├── 不联系包含0的数列.php ├── 二叉树搜索.php ├── 加权动态分配.php ├── 哈夫曼编码.php ├── 图着色:DFS.php ├── 字典排序.php ├── 布尔幂.php ├── 拓扑排序.php ├── 斐波那契数列.php ├── 普林算法.php ├── 树的遍历.php ├── 汉诺塔.php ├── 沃舍尔算法2.php ├── 波兰记法.php ├── 深度优先搜索.php ├── 点割集.php ├── 矩阵乘法.php └── 验证数据.php ├── README.md ├── 哈赛图.md ├── 图的同构.md ├── 常用LaTex 2.md ├── 常用LaTex.md ├── 常用LaTex3.md ├── 归谬证明.md ├── 有趣的概率问题.md ├── 沃舍尔算法.md ├── 离散数学.graffle ├── 第1章 基础:逻辑和证明 2.md ├── 第1章 基础:逻辑和证明.md ├── 第2章 集合、函数、序列、求和与矩阵.md ├── 第3章 算法.md ├── 第4章 数论和密码学.md ├── 辅助内容.xmind └── 顶点之间的通路数量.md /# 8.2 求解线性递推关系2.md: -------------------------------------------------------------------------------- 1 | ### 求解常系数线性非齐次递推关系 2 | 3 | [基础定义和前提内容](https://blog.csdn.net/YQXLLWY/article/details/113057829) 4 | 5 | 如果一个递推关系是非齐次的,形如: 6 | $$ 7 | a_n=c_1 \cdot {a}_{n-1}+c_2 \cdot {a}_{n-2}+c_1 \cdot {a}_{n-3} \cdots c_k \cdot {a}_{n-k}+F(n) \\ 8 | 且 F(n)只依赖于n,F(n) \neq 0 9 | $$ 10 | 其中`a_n`中齐次部分叫做:**相伴的齐次递推关系** 11 | 12 | 对于这种递推关系,其解有两部分组成: 13 | $$ 14 | {a}^{(h)}_{n}是相伴的齐次递推关系的一个解。\\ 15 | {a}^{(p)}_{n}是常系数线性非齐次递推关系的一个特解。\\ 16 | 其解的形式为:\\ 17 | ({a}^{(h)}_{n}+{a}^{(p)}_{n}) 18 | $$ 19 | 啥意思呢? 20 | $$ 21 | 简单来说就是首先要找到递推关系的一个特解:{a}^{(p)}_{n},啥叫特解呢?就是在这个解下,递推关系成立。因为解可能不止一个,所以叫做特解。\\ 22 | 然后就是去找相伴的齐次递推关系的解,两者一组合,就是原本递推关系的解了。 23 | $$ 24 | 先看一个例子,然后再说明上面的定理为什么是对的。例子: 25 | $$ 26 | 求:a_n=3 \cdot {a}_{n-1}+2n,a_1=3的解 27 | $$ 28 | 解题过程: 29 | $$ 30 | 这里的 F(n)=2n,于是我们就假设特解的形式为:F(n)=c\cdot n+d,其中c,d \in R。\\ 31 | 于是:a_n=cn+d=3\cdot (c(n-1)+d)+2n \\ 32 | 展开化解后:(2+2c)n+(2d-3c)=0。\\ 33 | 为了使 F(n)=c\cdot n+d 成为递推关系的特解,即真对所有的n都成立。\\ 34 | 必须:2+2c=0\ \cap\ 2d-3c=0。于是我们求的:{a}^{(p)}_{n}=-n-\frac{3}{2}\\ 35 | 下面再来求解相伴的齐次递推关系的解。根据 a_n=3 \cdot {a}_{n-1}可知,其解应该为 {a}^{(h)}_{n}=k \cdot 3^n\\ 36 | 于是我们套用上面的公式:\\ 37 | a_n={a}^{(p)}_{n}+{a}^{(h)}_{n}=-n-\frac{3}{2}+k\cdot 3^n \\ 38 | a_1=3=-1-\frac{3}{2}+k\cdot 3^1 \\ 39 | 求得:k=\frac{11}{6} \\ 40 | 于是a_n=-n-\frac{3}{2}+ \frac{11}{6} \cdot 3^n 41 | $$ 42 | 在借用了这个例子理解了上面各个部分的含义之后,接下来证明为什么上面的解的形式是有效的: 43 | $$ 44 | 因为 {a}^{(p)}_{n} 是递推关系的一个解,所以:\\ 45 | {a}^{(p)}_{n}=c_1 {a}^{(p)}_{n-1}+c_2 {a}^{(p)}_{n-2} \cdots c_k {a}^{(p)}_{n-k}+F(n)\\ 46 | 同时,设 b_n 为递推关系的另一个解,所以:\\ 47 | b_n=c_1 {b}_{n-1}+c_2 {b}_{n-2} \cdots c_k {b}_{n-k}+F(n)\\ 48 | 所以 \\ 49 | b_n-{a}^{(p)}_{n}=c_1 ({b}_{n-1}-{a}^{(p)}_{n-1})+c_2 ({b}_{n-2}-{a}^{(p)}_{n-2}) \cdots ({b}_{n-k}-{a}^{(p)}_{n-k}) \\ 50 | 可以看到结果是一个常系数线性齐次递推关系,定义其为{a}^{(h)}_{n}\\ 51 | 所以 b_n={a}^{(p)}_{n}+{a}^{(h)}_{n} 52 | $$ 53 | 54 | ---------------- 55 | 56 | 下面就是对于一种特殊情况的`F(n)`的通用解: 57 | $$ 58 | F(n)=(b_t n^t + {b}_{n-1} {n}^{t-1} \cdots b_1 n+b_0)\cdot s^n,其中 b_1,b_2 \cdots b_0,s \in R 时,\\ 59 | 当 s 不是相伴齐次递推关系的根时,特解形式为:\\ 60 | (p_t n^t + {p}_{n-1} {n}^{t-1} \cdots p_1 n+p_0)\cdot s^n \\ 61 | 当 s 时相伴齐次递推关系的根,且其重数为m时,特解形式为:\\ 62 | n^m \cdot (p_t n^t + {p}_{n-1} {n}^{t-1} \cdots p_1 n+p_0)\cdot s^n 63 | $$ 64 | 例子: 65 | $$ 66 | a_n=6 {a}_{n-1}-9 {a}_{n-2}+F(n)的特解,在F(n)=3^n,F(n)=n 3^n,F(n)=n^2 2^n,F(n)=(n^2+1) 3^n时,分别为多少? 67 | $$ 68 | 解决过程: 69 | $$ 70 | 相伴的齐次递推关系为:a_n=6 {a}_{n-1}-9 {a}_{n-2},其特征方程为 r^2-6n+9=(r-3)^2=0,其特征根为一个2重根3。\\ 71 | 所以当 F(n)=3^n时,特解形式为 n^2 p_0 3^n \\ 72 | 当 F(n)=n3^n时,特解形式为 n^2 (p_1n+p_0) 3^n \\ 73 | 当 F(n)=n^2 2^n时,特解形式为 (p_2 n^2+p_1n+p_0) 2^n\\ 74 | 当 F(n)=(n^2+1) 3^n时,特解形式为 n^2 (p_2 n^2+p_1n+p_0) 3^n 75 | $$ 76 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | 数论和密码学.graffle 3 | 4 | 高级计数计数.graffle 5 | -------------------------------------------------------------------------------- /10.1 图和图模型.md: -------------------------------------------------------------------------------- 1 | # 10 图的基础知识 2 | 3 | ### 无向图和有向图 4 | 5 | > 图G=(V,E)由顶点(或结点)的非空集V和边集E构成,每条边有1个或2个顶点与它相连,这样的顶点称为边的端点。即边连接它的端点。 6 | 7 | 8 | 9 | > 有向图G=(V,E)由一个非空顶点集V和一个有向边(或弧)集E组成。每条有向边与一个顶点有序对相关联。 10 | > 11 | > 我们称有序对(u,v)相关联的有向边开始于u,称为起点,结束于v,称为终点。 12 | > 13 | > 环的起点和终点是一样的。 14 | 15 | ### 图的术语 16 | 17 | #### 领接 / 相邻 18 | 19 | 就是一条边连接两个顶点,相互之间领接。 20 | $$ 21 | 假设一个顶点:u,所有和u相邻的顶点组成的集合记做N(u),称为u的邻居。\\ 22 | 再来将上面的一个顶点,扩充成一个集合:A,则该集合中所有顶点的邻居就是\\ 23 | N(A)=\bigcup_{u \in A}N(u) 24 | $$ 25 | 26 | #### 度 27 | 28 | 就是一个顶点`u`相连接的边的数量,记做`deg(u)`。 29 | $$ 30 | 在有向图中,{deg}^{-}(u)是以u为终点的边的数量。\\ 31 | {deg}^{+}(u)是以u为起点的边的数量。\\ 32 | 所以\\ 33 | \sum_{u \in V} {deg}^{-}(u)=\sum_{v \in V} {deg}^{+}(v)=|E| 34 | $$ 35 | [|E|代表集合的基数,即集合的大小](https://blog.csdn.net/YQXLLWY/article/details/111305452) 36 | 37 | 最后的那个公式很容易理解吧,所有顶点作为终点时,必要有对应的顶点作为起点,所以两者的总和是一样的。 38 | 39 | ### 握手定理 40 | 41 | $$ 42 | 设G=(V,E),有m条边,那么 \\ 43 | \sum_{u \in V} deg(u)=2m 44 | $$ 45 | 46 | 这个很容易理解吧,假设顶点a和b相邻,之间存在一条边,那么在计算`deg(a)`的时候这条边被计算一个,计算`deg(b)`的时候,这条边又被算了一次。 47 | 48 | --------- 49 | 50 | 下面介绍一些特殊的图: 51 | 52 | #### 完全图 53 | 54 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnh9w5zr1xj309z0aoq3b.jpg) 55 | $$ 56 | 完全图记做 K_n,即每个顶点都与集合中的其他顶点相邻。n代表了顶点数量。n>=1。 57 | $$ 58 | 59 | 60 | #### 圈图 61 | 62 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnh9wi6728j308y0alt8r.jpg) 63 | $$ 64 | 圈图记做 C_n,即每个顶点只与自己邻近的顶点相邻。n>=3 65 | $$ 66 | 67 | 68 | #### 轮图 69 | 70 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnh9x79415j308v0ajdg0.jpg) 71 | $$ 72 | 轮图记做 W_n,即在圈图的基础上,增加一个顶点与其他顶点都连接。n>=3。 73 | $$ 74 | 75 | #### n立方题图 76 | 77 | 这个很有意思,首先就是每个顶点都有一个二进制编码,然后相邻的顶点就是只有1个二进制编码的位置不同,比如下面这些: 78 | 79 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnhaagedx8j30g209sjro.jpg) 80 | 81 | ## 二分图 82 | 83 | 简单点来说就是将顶点分为两个子集合,这两个集合中的顶点都不与自己集合中的顶点相连。比如下面的绿色点集合和红色的点集合。 84 | 85 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnhaz1lo6kj30cg0860t0.jpg) 86 | 87 | 我个人感觉,如果类比[关系中的传递性质](https://blog.csdn.net/YQXLLWY/article/details/113480886)来说的话,那就是如果该图具有传递性质,那么就不是二分图了。 88 | 89 | #### 完全二分图 90 | 91 | 就是在一个集合中,每个顶点都与另一个集合中的顶点相邻。 92 | 93 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnhb4lbaq4j30bd06m3yx.jpg) 94 | 95 | ### 子图 96 | 97 | 就是在原来图的基础上,删除了一些顶点和对应的边,或者删除了边与对应的顶点后的图,称作子图。 98 | 99 | -------------------------------------------------------------------------------- /10.4 连通性.md: -------------------------------------------------------------------------------- 1 | # 10.4 连通性:基础概念介绍 2 | 3 | 下面的所有的图都是无向图。 4 | 5 | ## 通路 6 | 7 | 就是很简单的,比如下面的图中: 8 | 9 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnhe9luqcxj309m07it8m.jpg) 10 | 11 | 从点a到点c,`(a,b,c)`是通路,`(a,d,c)`也是,但是`(a,c)`不是,因为没有这条边。 12 | 13 | 回路,圈等就是起点和终点的顶点相同,且通路长度不为0。 14 | 15 | ## 连通性 16 | 17 | > 如果图中的每个顶点之间都有通路,那该图就称为连通的。 18 | 19 | 说人话就是能没有孤立的点,可以通过通路,从一个点走到任何另一个点。 20 | 21 | ## 割点 / 关节点 & 割边 / 桥 22 | 23 | 就是在连通性的图上,如果少了该顶点,或者少了该边,就组成了两个连通性的图,那么少了点这个顶点,就叫做割点,或者关节点,边就叫做割边,或者桥。 24 | 25 | 比如下面的这张图: 26 | 27 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnhetlrgcwj30lm07vwep.jpg) 28 | 29 | 我们一个顶点一个顶点的看: 30 | 31 | | 顶点 | 是否是割点 | 32 | | ---- | ---------- | 33 | | a | 不是 | 34 | | b | 不是 | 35 | | c | 是 | 36 | | d | 是 | 37 | | e | 不是 | 38 | | f | 不是 | 39 | | g | 是 | 40 | | h | 不是 | 41 | 42 | 再来一条边一条边的看: 43 | 44 | | 边 | 是否是割边 | 45 | | ---- | ---------- | 46 | | a,d | 是 | 47 | | d,c | 不是 | 48 | | b,d | 不是 | 49 | | b,c | 不是 | 50 | | c,g | 是 | 51 | | e,g | 不是 | 52 | | g,f | 不是 | 53 | | g,h | 不是 | 54 | | f,h | 不是 | 55 | | e,f | 不是 | 56 | 57 | 不是所有的图都是可分割的,比如[完全图](https://blog.csdn.net/YQXLLWY/article/details/113771353)就是不可割图。 58 | 59 | ## 点割集 / 分割集 60 | 61 | 割点组成的集合,就叫做点割集,或者分割集。 62 | 63 | ## 连通度 64 | 65 | 注意,这里开始就不考虑点割集的概念了,即下面的点都不叫割点了。但是对于点割集来说,连通度也是有意义的,只是是固定值1。 66 | 67 | 上面我们都是说删除一个点,使得原本的图变成更多的连通图,但是一些图只删除一个点并不能使其变成更多的连通图,比如可能需要删除2个,3个顶点。比如下面的这张图: 68 | 69 | ![XpFbiGVBLh8H6do](https://i.loli.net/2021/02/11/XpFbiGVBLh8H6do.png) 70 | 71 | 仅仅删除任何一个点,都不足以产生更多的连通图。至少需要删除2个点才可以,比如`(b,e)`,`(b,d)`,`(e,c)`等。 72 | 73 | 所以这里我们增加一个概念:连通度。含义就是至少要删除这些数量的点,才可以使原本的图产生更多的连通图。 74 | $$ 75 | 我们使用 \kappa (G)=2来表示一个图的连通度。G代表对应的图。\\ 76 | 所以,对于连通图 K_n 来说,\kappa(K_n)=n-1。\\ 77 | 同时,对于不连通的图来说,\kappa(G)=0。 78 | $$ 79 | [k_n代表n个顶点的完全图](https://blog.csdn.net/YQXLLWY/article/details/113771353),至于连通图的公式由来,假设我们要使完全图中的一个点不连通,只有删除除了它之外的其他所有点才可以。 80 | 81 | --------------- 82 | 83 | 这里做一下汇总: 84 | 85 | ![w2PLVMzSiQcY49F](https://i.loli.net/2021/02/11/w2PLVMzSiQcY49F.png) 86 | $$ 87 | 如果一个图的 \kappa (G)>=k,则称图为 k连通的,或 k顶点连通的。 88 | $$ 89 | 对于3个顶点的完全图,我们可以称呼它为双连通图(因为它是2连通的)。 90 | 91 | ------------ 92 | 93 | 上面只考虑了顶点,对应的边也有类似的定义。 94 | 95 | ## 边隔集 & 边连通度 96 | 97 | $$ 98 | 边连通度记为 \lambda (G)=k。\\ 99 | 对于完全图 K_n, \lambda(K_n)=n-1,因为我们需要删除与我们选定的点所有连接的边,才可以使该图不连通。 100 | $$ 101 | 102 | -------------------------------------------------------------------------------- /10.4 连通性:结论.md: -------------------------------------------------------------------------------- 1 | # 10.4 连通性:结论 2 | 3 | [以下的名词及其解释都来自这里](https://blog.csdn.net/YQXLLWY/article/details/113790328) 4 | $$ 5 | \kappa(G) \leq \lambda(G) \\ 6 | 这个很容易理解,分情况来考虑:\\ 7 | 对于不连通的图:\kappa(G)=\lambda(G)=0\\ 8 | 对于有割点集的图:\kappa(G)=\lambda(G)=1\\ 9 | 对于没有割点集的连通图:\\ 10 | 我们从分割后的完全连通图考虑,被删除的边,假设为y,其终点可能指向y个点,\\ 11 | 换句话说,删除这y个点,也可以实现创建更多完全连通图的效果。\\ 12 | 但是这y条边一定指向y个顶点吗?不一定,其中可以有2条边指向同一个顶点。\\ 13 | 所以:\\ 14 | \kappa(G) \leq \lambda(G) 15 | $$ 16 | 比如下面的这张图: 17 | 18 | ![jDc6GAmYFJdqly9](https://i.loli.net/2021/02/11/jDc6GAmYFJdqly9.png) 19 | 20 | ------------ 21 | 22 | $$ 23 | 如果 G=(V,E),且 G 不是完全图,|V| \geq 3,那么\\ 24 | \kappa(G) \leq \min_{v \in G} \ deg(v)\\ 25 | \lambda(G) \leq \min_{v \in G} \ deg(v) 26 | $$ 27 | 28 | [deg的含义见这里,即一个顶点连接的边的数量](https://blog.csdn.net/YQXLLWY/article/details/113771353) 29 | 30 | 这个从反面考虑就很简单了: 31 | $$ 32 | 考虑到 \lambda 的定义,就知道 \lambda (G) \geq \min_{v \in G} \ deg(v) 的情况是不可能的。\\ 33 | 所以 \lambda (G) \leq \min_{v \in G} \ deg(v) \\ 34 | 同时 \kappa(G) \leq \lambda(G),所以同时 \kappa (G) \leq \min_{v \in G} \ deg(v) 35 | $$ 36 | 37 | ------------- 38 | 39 | # 有向图 40 | 41 | 之前一直在说明无向图,这里讨论一下有向图。 42 | 43 | ### 连通 44 | 45 | 这个概念在有向图中就是加上了方向的属性。有向图的连通分为**强连通**和**弱连通**。 46 | 47 | 先说强连通,就是如果方向走,可以从一个顶点走到任何一个顶点。 48 | 49 | ![G6QN9FrntKaR5qe](https://i.loli.net/2021/02/12/G6QN9FrntKaR5qe.png) 50 | 51 | 比如这张图,可以从任何一个顶点都其他任何一个顶点。 52 | 53 | 而下面这张图则不是强连通,因为没有办法从a到b。 54 | 55 | ![9l2dSx7q3t8OXeh](https://i.loli.net/2021/02/12/9l2dSx7q3t8OXeh.png) 56 | 57 | 而弱连通就是将方向去掉,用无向图的标准考虑连通性。比如上面这张图,就是弱连接的,当然,如果一张图是强连接的,那么它肯定也是弱连通的。 58 | 59 | 从一个强连接图中拆分出部分的子图,并且该部分子图如果也是强连接的,那么该部分就称为**强连通分支**,或者**强分支**。 60 | 61 | # 同构 62 | 63 | [同构的定义](https://blog.csdn.net/YQXLLWY/article/details/113772152) 64 | 65 | “ 66 | 67 | > 长度为k的简单回路的存在性是一个图同构的不变量,其中k是大于2的正整数。 68 | 69 | ” 70 | 71 | 先解释啥叫**简单**,就是从一个顶点到另一个顶点只有一条边,没有重复边。 72 | 73 | 再来就是上面那句话啥意思呢?就是如果两个图重构,则其回路的长度一定是一致的。加上如果两个图是重构的,顶点的数量,边的数量也一定是相同的,这些条件加在一起就是判断两个图是否重构的一个判定标准。 74 | 75 | 比如下面的这两张图: 76 | 77 | ![gjZWQtJ1mSP2v3R](https://i.loli.net/2021/02/12/gjZWQtJ1mSP2v3R.png) 78 | 79 | 其都具有5个顶点,6条边,并且右边的图具有长度为4和3的简单回路,左边的也具有长度为3和4的简单回路,所以两个图同构,这里将左边的图加工一下,看的更清楚。 80 | 81 | ![OTgjYqF4nJV1yws](https://i.loli.net/2021/02/12/OTgjYqF4nJV1yws.png) 82 | 83 | 但是下面的两张图就不是同构的: 84 | 85 | ![48pkgX2Lir9Qj7q](https://i.loli.net/2021/02/12/48pkgX2Lir9Qj7q.png) 86 | 87 | 虽然顶点和边的数量一致,但是左边的具有长度为3和4的简单回路,而右边的则是只有长度为4的简单回路。我当时第一眼看的时候以为两张图是同构的,但是我在这里画一下结果,防止我以后又会这么想: 88 | 89 | ![LuNx7gt1lykofYW](https://i.loli.net/2021/02/12/LuNx7gt1lykofYW.png) 90 | 91 | -------------------------------------------------------------------------------- /10.5 欧拉通路与哈密顿通路.md: -------------------------------------------------------------------------------- 1 | # 10.5 欧拉通路与哈密顿通路 2 | 3 | ## 欧拉通路和欧拉回路 4 | 5 | > 图G中的欧拉回路是包含G的每一条边的简单回路。 6 | > 7 | > 图G中的欧拉通路是包含G的每一条边的简单通路。 8 | 9 | 啥意思呢?先解释简单,即两个顶点之间不能拥有2条边。再来就是需要包含图中的每条边,最后就是回路需要开点和终点一致。 10 | 11 | 比如下面的这张图: 12 | 13 | ![u3dlcDBijGsz95T](https://i.loli.net/2021/02/13/u3dlcDBijGsz95T.png) 14 | 15 | 欧拉回路: 16 | 17 | 1. a-b 18 | 2. b-c 19 | 3. c-e 20 | 4. e-d 21 | 5. d-c 22 | 6. c-a 23 | 24 | 欧拉通路可以直接拿欧拉回路来当例子说明。 25 | 26 | 再比如下面这张图: 27 | 28 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnlzfwyp37j30d309p74c.jpg) 29 | 30 | 欧拉回路:不存在。 31 | 32 | 欧拉通路: 33 | 34 | 1. a-c 35 | 2. c-d 36 | 3. d-e 37 | 4. e-b 38 | 5. b-d 39 | 6. d-a 40 | 7. a-b 41 | 42 | 到这里就可以理解欧拉通路和欧拉回路的定义了。 43 | 44 | ---------- 45 | 46 | 上面是直接写出对应的欧拉回路,以此证明该图欧拉回路的存在,下面就是说明欧拉回路存在的必要条件: 47 | 48 | > 含有至少2个顶点的连通多重图具有欧拉回路当且仅当它的每个顶点的度都为偶数。 49 | 50 | 或者表示成下面的形式: 51 | $$ 52 | \forall v \in V (deg(v) \mod 2==0) 53 | $$ 54 | 说人话就是每个顶点的边的数量都是偶数。 55 | 56 | [证明过程可以看这个油管的视频](https://www.youtube.com/watch?v=vjpzmnVuHjw&t=812s) 57 | 58 | 这里简单说明一下,首先先从任何一个点开始,按照这个点的边开始前进到下一个点,因为每个点都是偶数边,所以肯定能满足一进一出,因为该图具有连通性,所以肯定可以回到起点。比如下面这张图,以a为起点: 59 | 60 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnmvziadcwj30e90fw0t9.jpg) 61 | 62 | 然后我们可以看到,其中一些边是没有走到的,然后我们就以图中没有被包含进去的边为顶点,继续走上面的步骤,这里以c为例子: 63 | 64 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnmw09m1yhj30dk0g874s.jpg) 65 | 66 | 然后继续上面的步骤,依次以f和e为例子,构建回路: 67 | 68 | ![image-20210214111307748](https://tva1.sinaimg.cn/large/008eGmZEgy1gnmw3fgl66j30d80fpjrw.jpg) 69 | 70 | 我知道这玩意更加像是构建回路的过程,而不像是证明的过程,但是如果上面的步骤一定能完成,那么即证明了如果满足上面的条件,则欧拉回路肯定存在。 71 | 72 | 最终上面这张图的欧拉回路为: 73 | 74 | - a-c 75 | - c-d 76 | - d-b 77 | - b-c 78 | - c-f 79 | - f-d 80 | - d-e 81 | - e-g 82 | - g-f 83 | - f-e 84 | - e-b 85 | - b-a 86 | 87 | -------------- 88 | 89 | 欧拉通路的存在则是: 90 | 91 | > 连通多重图具有欧拉通路但无欧拉回路当且仅当它恰有2个度为奇数的顶点。 92 | 93 | 说人话就是如果一个图中,只有2个顶点的边的是奇数,则其就只有欧拉通路,但是没有欧拉回路。 94 | 95 | 这个证明还是看上面的那个油管视频。简单来说就是比起欧拉回路少一条边就可以了,正是因为少了这一条边,所以就产生了两个顶点的边为奇数的情况。 96 | 97 | ## 哈密顿通路与哈密顿回路 98 | 99 | 这里对比一下,可以更好理解啥叫哈密顿通路和回路: 100 | 101 | | 对比项目 | 欧拉回路 / 欧拉通路 | 哈密顿回路 / 哈密顿通路 | 102 | | -------- | ---------------------------------- | ----------------------------------- | 103 | | 每个点 | 可以经过多次,而且不需要都经过 | 每个顶点只能经过1次,而且都需要经过 | 104 | | 每条边 | 每条边只能经过一次,而且都需要经过 | 可以经过多次,而且不需要都经过 | 105 | 106 | 简单来说就是将欧拉回路中的点和边的要求互换。 107 | 108 | 比如下面的这幅图: 109 | 110 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnmyxhr29gj307008vjri.jpg) 111 | 112 | 就具有哈密顿回路:a-b-c-e-d-a 113 | 114 | 自然也有哈密顿通路。 115 | 116 | 但是下面这幅图,就只能哈密顿通路,但是没有哈密顿回路了: 117 | 118 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnmz15ogbgj306s08b3yj.jpg) 119 | 120 | ---------- 121 | 122 | 哈密顿通路好像暂时没有充要条件,但是哈密顿通路存在的充分条件有了: 123 | 124 | ### 狄拉克定理 125 | 126 | > 如果图G是有n个顶点的简单图,其中n>=3,并且G中每个顶点的度都至少为n/2,则G有哈密顿回路。 127 | 128 | [顶点度的定义见这里,其实就是每个顶点的边的数量](https://blog.csdn.net/YQXLLWY/article/details/113771353) 129 | 130 | 充分条件就是:如果A成立,B就肯定成立,则A是B的充分条件。同时,B不一定都具有A的性质。对应到上面就是,并不是所有的哈密顿回路都具有狄拉克定理中的性质。 131 | 132 | ### 欧拉定理 133 | 134 | > 如果G是有n个顶点的简单图,其中n>=3,并且对于G中每一对不相邻的顶点u和v来说,都有 deg(u)+deg(v)>=n,则G有哈密顿回路。 135 | 136 | [证明可以看这个油管视频,但是我觉得我没看懂](https://www.youtube.com/watch?v=HE3b6Eow4lk&list=PLBPbUxsZM4SbFoinAoJXoNAAiGRuPLm4J&index=102) 137 | 138 | 这里我试着说明一下: 139 | $$ 140 | 如果是完全图的话,其肯定具有哈密顿回路。\\ 141 | 所以借由完全图来说明。\\ 142 | n个顶点的完全图,其边的总数为 \frac{(n-1)n}{2}\\ 143 | 去掉两个点之后,少掉的边数量为 n-1+n-1-1=2n-3\\ 144 | 则剩余的边的数量为:\frac{(n-1)n}{2}-(2n-3)=\frac{n^2-5b+6}{2}=\frac{(n-2)(n-3)}{2} \geq 0\\ 145 | 假设 deg(u)+deg(v) < n,即 2n-3 < n,即n<3,则结合上面的结论 n<2,即 n=1。但是我们考虑的肯定不是 n=1的情况,所以\\ 146 | deg(u)+deg(v) \geq n 147 | $$ 148 | 我自己都觉得这证明很鬼扯。。。。。。 149 | 150 | 然后你就可以用欧拉定理来推导出狄拉克定理。更鬼扯了。 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /10.6 最短通路问题.md: -------------------------------------------------------------------------------- 1 | # 10.6 最短通路问题:BFS 和 DFS 2 | 3 | [参考的一个油管视频,中文的,讲解的很好](https://www.youtube.com/watch?v=oLtvUWpAnTQ&list=PLAnjpYDY-l8IacYv_2lIZxNrQmkY3paSN&index=2) 4 | 5 | BFS:广度优先搜索算法 6 | 7 | DFS:迪克斯特拉算法 8 | 9 | ## BFS 10 | 11 | 这里先介绍广度优先算法,它能处理没有加权的最短路径。具体步骤很简单,举个例子就行了,比如下面这张图: 12 | 13 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnn1womqknj30io0ab0t6.jpg) 14 | 15 | 你人在上海,你需要去广州,那么如何获取最短路径呢?首先你先确定从上海出发,能够到达的城市有哪些,接下来,再依次考虑这些城市能到达的下一个城市,其中最快能确定到达广州的,就是你的路线图。具体步骤如下: 16 | 17 | 1. 考量的城市:上海 18 | 2. 考量的城市:南京,深圳 19 | 3. 考量的城市:北京,武汉,广州 20 | 21 | 这里已经命中了广州,所以最短路径为:上海-深圳-广州。 22 | 23 | 再来是具体的代码: 24 | 25 | ```php 26 | ['南京','深圳'], 32 | '南京'=>['上海','北京','武汉'], 33 | '深圳'=>['上海','广州'], 34 | '武汉'=>['南京','北京','广州'], 35 | '北京'=>['南京','武汉','广州'], 36 | '广州'=>['深圳','武汉','北京'] 37 | ]; 38 | 39 | function BFS($map,$finalCity,$nextCities,&$passedCities){ 40 | $nextTurnCity=[]; 41 | /** 42 | * 遍历这一轮需要检验的城市 43 | */ 44 | foreach($nextCities as $thisCity){ 45 | foreach($map[$thisCity] as $nextCity){ 46 | $passedCities[$nextCity]=$thisCity; 47 | if($nextCity==$finalCity){ 48 | showResult($passedCities,$finalCity); 49 | return true; 50 | } 51 | /** 52 | * 防止出现 上海 - 南京,南京 - 上海 这样的死循环 53 | */ 54 | $nextTurnCity[]=$nextCity; 55 | } 56 | } 57 | // 开始递归 58 | BFS($map,$finalCity,$nextTurnCity,$passedCities); 59 | } 60 | 61 | // 展示输出结果 62 | function showResult($map,$startCity,&$checkedCity=[]){ 63 | if(isset($checkedCity[$startCity])){ 64 | return false; 65 | } 66 | print $startCity.DIRECTORY_SEPARATOR; 67 | $checkedCity[$startCity]=1; 68 | showResult($map,$map[$startCity],$checkedCity); 69 | } 70 | 71 | $result=[]; 72 | BFS($map,'广州',['上海'],$result); 73 | // 输出结果为: 74 | // 广州/深圳/上海/% 75 | ``` 76 | 77 | ## DFS 78 | 79 | DFS就是在上面的图上,每条边加上权重。 80 | 81 | 具体步骤可以[参考这个B站视频](https://www.bilibili.com/video/BV1mt411i7DX?from=search&seid=7147247003165627301) 82 | 83 | 然后我这边简单说明一下,像下面这张图: 84 | 85 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnn6v5t1p8j30e907wwew.jpg) 86 | 87 | 然后开始维护下面这张表: 88 | 89 | | 点 | 最短距离 | 前一个点 | 90 | | ---- | -------- | -------- | 91 | | A | 无穷大 | 无 | 92 | | B | 无穷大 | 无 | 93 | | C | 无穷大 | 无 | 94 | | D | 无穷大 | 无 | 95 | | E | 无穷大 | 无 | 96 | 97 | 然后从起点A开始: 98 | 99 | | 点 | 最短距离 | 前一个点 | 100 | | ---- | --------------------------------- | -------- | 101 | | A | 0(因为自身到自身不需要任何距离) | 无 | 102 | | B | 无穷大 | 无 | 103 | | C | 无穷大 | 无 | 104 | | D | 无穷大 | 无 | 105 | | E | 无穷大 | 无 | 106 | 107 | 然后开始考虑A所能到达的边,即B和D,注意,**这里是递归的开始**: 108 | 109 | | 点 | 最短距离 | 前一个点 | 110 | | --------- | -------- | -------- | 111 | | A:已处理 | 0 | 无 | 112 | | B | 6 | A | 113 | | C | 无穷大 | 无 | 114 | | D | 1 | A | 115 | | E | 无穷大 | 无 | 116 | 117 | 然后我们比较B和D中比较小的那个点开始当作下一个点,这里选择的是D,考虑D的边连通的顶点,即B和E,A因为已经递归过了,所以不在考虑的范畴之内: 118 | 119 | | 点 | 最短距离 | 前一个点 | 120 | | --------- | ----------------------------------------------------------- | -------- | 121 | | A:已处理 | 0 | 无 | 122 | | B | 3(因为从C到B的值比起B原先的值小,所以更新B的值和前一个点) | D | 123 | | C | 无穷大 | 无 | 124 | | D:已处理 | 1 | A | 125 | | E | 2 | D | 126 | 127 | 然后重复上面的步骤,选择E作为考虑的顶点,考虑B和C: 128 | 129 | | 点 | 最短距离 | 前一个点 | 130 | | --------- | ------------------------------------------------------- | -------- | 131 | | A:已处理 | 0 | 无 | 132 | | B | 3(如果从E走到B,值是4,比原先的值大,所以不更新B的值) | D | 133 | | C | 7 | E | 134 | | D:已处理 | 1 | A | 135 | | E:已处理 | 2 | D | 136 | 137 | 接下来就是考虑顶点B,以及与其邻接的C,因为A,D,E都已经处理过了,所以不再考虑了: 138 | 139 | | 点 | 最短距离 | 前一个点 | 140 | | --------- | ------------------------------------------------------- | -------- | 141 | | A:已处理 | 0 | 无 | 142 | | B:已处理 | 3 | D | 143 | | C | 7(如果从B走到C,则值为8,比原先的大,所以不更新C的值) | E | 144 | | D:已处理 | 1 | A | 145 | | E:已处理 | 2 | D | 146 | 147 | 这样到最后我们就已经处理到了最后的终点,C,递归结束。从A到C的最短距离即是: 148 | 149 | - C - E - D - A 150 | 151 | 对应的代码为: 152 | 153 | ```php 154 | label=$label; 166 | } 167 | } 168 | /** 169 | * $nodes 就是模拟前面讲解时采用的表 170 | * $map 对应的图 171 | * $thisNode 递归时采用的点 172 | * $resultNodeLabel 终点 173 | */ 174 | function DFS(&$nodes,$map,&$thisNode,$resultNodeLabel){ 175 | $nextTurnLabel=''; 176 | $minValue=null; 177 | foreach($map[$thisNode->label] as $nextLabel=>$value){ 178 | $node=$nodes[$nextLabel]; 179 | if($node->isChecked){ 180 | continue; 181 | } 182 | if(is_null($node->value) || ($thisNode->value+$value)<$node->value){ 183 | $node->value=$thisNode->value+$value; 184 | $node->previousNodeLabel=$thisNode->label; 185 | if(is_null($minValue) || $node->value<$minValue){ 186 | $minValue=$node->value; 187 | $nextTurnLabel=$node->label; 188 | } 189 | } 190 | } 191 | $thisNode->isChecked=true; 192 | if($thisNode->label==$resultNodeLabel){ 193 | return true; 194 | } 195 | if($nextTurnLabel){ 196 | DFS($nodes,$map,$nodes[$nextTurnLabel],$resultNodeLabel); 197 | } 198 | } 199 | 200 | function showResult($nodes,$label){ 201 | if(!$label){ 202 | return false; 203 | } 204 | print $label.DIRECTORY_SEPARATOR; 205 | $preNode=$nodes[$label]; 206 | showResult($nodes,$preNode->previousNodeLabel); 207 | } 208 | 209 | $map=[ 210 | 'A'=>['D'=>1,'B'=>6], 211 | 'D'=>['A'=>1,'B'=>2,'E'=>1], 212 | 'B'=>['A'=>6,'D'=>2,'E'=>2,'C'=>5], 213 | 'E'=>['D'=>1,'B'=>2,'C'=>5], 214 | 'C'=>['B'=>5,'E'=>5] 215 | ]; 216 | 217 | $startNode=new Node('A'); 218 | $resultLable='C'; 219 | // 可以试试看不走到最后一步,走到中间过程 220 | // $resultLable='E'; 221 | $nodes=[ 222 | 'A'=>$startNode, 223 | 'B'=>new Node('B'), 224 | 'C'=>new Node('C'), 225 | 'D'=>new Node('D'), 226 | 'E'=>new Node('E') 227 | ]; 228 | 229 | DFS($nodes,$map,$startNode,$resultLable); 230 | 231 | showResult($nodes,$resultLable); 232 | ``` 233 | 234 | -------------------------------------------------------------------------------- /10.7 平面图.md: -------------------------------------------------------------------------------- 1 | # 10.7 平面图 2 | 3 | > 若可以在平面中画出一个图而边没有任何交叉(其中边的交叉时表示边的直线或弧线在它们的公共端点以外的地方相交),则这个图是平面图。这种画法称为这个图的平面表示。 4 | 5 | 简单来说就是将原来的图采用平面图的形式表示,并且其中的边不交叉。比如下面这张图: 6 | 7 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnnbopkkhvj308f06xa9z.jpg) 8 | 9 | 采用平面图表示后如下所示: 10 | 11 | ![image-20210214201359307](https://tva1.sinaimg.cn/large/008eGmZEgy1gnnbq7ltz0j309g07hwef.jpg) 12 | 13 | ## 欧拉公式 14 | 15 | > 设G是带e条边和u个顶点的连通平面简单图。设r是G的平面图表示中的面数,则r=e-u+2。 16 | 17 | 比如上面的例子中: 18 | 19 | - e=12 20 | - u=8 21 | - r=6 22 | 23 | 这里解释一下r=6的由来: 24 | 25 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gno7sdtlcuj30fy08hq3c.jpg) 26 | 27 | 证明就算了,直接拿过来用吧。 28 | 29 | 推论1: 30 | 31 | > 若G是e条边和u个顶点的连通平面简单图,其中u>=3,则e<=3u-6 32 | 33 | [度的概念见这里,以及之后要用到的握手定理](https://blog.csdn.net/YQXLLWY/article/details/113771353)。 34 | 35 | 证明: 36 | $$ 37 | 根据握手定理:2e=\sum_{u \in U}deg(u) \\ 38 | 因为至少3条边组成一个面,所以 \sum_{u \in U}deg(u) \geq 3r,即 2e \geq 3r\\ 39 | 再套用到欧拉公式中,用e和u替换r,最终结果为\\ 40 | e \leq 3u-6 41 | $$ 42 | 推论2: 43 | 44 | > 若G是连通平面简单图,则G中有度数不超过5的顶点。 45 | 46 | 证明: 47 | $$ 48 | 假设G中没有度数不超过5的顶点,即每个顶点的最小度数为6。\\ 49 | 根据握手定理:2e=\sum_{u \in U}deg(u),所以 2e \geq 6u,即 e \geq 3u,结合推论1,就可以知道这是不可能的。\\ 50 | 所以原命题为真。 51 | $$ 52 | 推论3: 53 | 54 | > 若连通平面简单图有e条边和u个顶点,u>=3,并且每个顶点的度至少为4,那么 e<=2u-4 55 | 56 | 证明很简单,还是老套路,用握手定理确定边与顶点的关系,然后用欧拉公式替换其中的r参数。 57 | 58 | 书上说可以用这个来判断一个图是否为平面图。比如`k3.3`所代表的完全二分图: 59 | 60 | ![image-20210215192623271](https://tva1.sinaimg.cn/large/008eGmZEgy1gnofyzpwq7j308o0850sw.jpg) 61 | 62 | 本来用欧拉公式就可以了,但是奈何面数太难数了,而且之所以不用推论1,是因为在推论1下它是成立的,所以用推论3。 63 | 64 | ------- 65 | 66 | ## 康拉图斯基定理 67 | 68 | 不用管他书上的一堆名词解释,简单来说就是如果一个图中包含`K5`和`K3.3`的话,那么它就不是平面图。 69 | 70 | 比如下面这张图中就包含了`K3.3`: 71 | 72 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnogjh1nqwj30j10h40tn.jpg) 73 | 74 | 其中藏的`k3.3`就是如下所示: 75 | 76 | ![image-20210215194651272](https://tva1.sinaimg.cn/large/008eGmZEgy1gnogk8xcofj30dp0d2wf7.jpg) 77 | 78 | 所以它不是平面图。 79 | 80 | -------------------------------------------------------------------------------- /10.8 图着色.md: -------------------------------------------------------------------------------- 1 | # 10.8 图着色 2 | 3 | > 简单图的着色是对该图的每个顶点都指定一种颜色,使得没有两个相邻的顶点颜色相同。 4 | 5 | 这个很简答吧,如下图所示: 6 | 7 | ![image-20210215200149017](https://tva1.sinaimg.cn/large/008eGmZEgy1gnogztonpnj30jh0f7dgr.jpg) 8 | $$ 9 | 图的着色数是着色这个图所需要的最少颜色数。图G的着色数记做 \chi(G)。 10 | $$ 11 | 12 | ## 四色定理 13 | 14 | > 平面图的着色数不超过4。 15 | 16 | 这个证明我自己想的,应该没有问题: 17 | 18 | 对于一个原本的图形,我在每个面上加上一个点,如下图所示: 19 | 20 | ![image-20210215202606756](https://tva1.sinaimg.cn/large/008eGmZEgy1gnohp3hmicj30a1079jrq.jpg) 21 | 22 | 这样等于将它的平面图都变成了1个1个的小三角形,如下所示: 23 | 24 | ![image-20210215202711170](https://tva1.sinaimg.cn/large/008eGmZEgy1gnohq7gzqxj30ej0bojs9.jpg) 25 | 26 | 这样考虑着色的时候,只需要考虑一个又一个三角形组成的图了,而这种情况下,只需要3到4种颜色就可以涂完所有的点了: 27 | 28 | 如下图所示: 29 | 30 | ![image-20210215202932963](https://tva1.sinaimg.cn/large/008eGmZEgy1gnohsnzsx0j30dz0br0tm.jpg) 31 | 32 | 而且对于任何平面的物体,你都可以在上面加一个点,然后构建成上面的形式,至于是3种还是4种,具体看你对应的面是奇数还是偶数了,看下图: 33 | 34 | ![image-20210215203527078](https://tva1.sinaimg.cn/large/008eGmZEgy1gnohysylibj30hk091q3i.jpg) 35 | 36 | 到另一个面时,只是上面过程的重复。 37 | 38 | -------------------------------------------------------------------------------- /11.1 树的概述:基础定义.md: -------------------------------------------------------------------------------- 1 | # 11.1 树的概述:基础定义 2 | 3 | > 树是没有简单回路的连通无向图。 4 | > 5 | > 一个无向图是树当且仅当它的每队顶点之间存在唯一简单通路。 6 | 7 | [回路的定义见这里](https://blog.csdn.net/YQXLLWY/article/details/113790328) 8 | 9 | 然后由多个树组成的图就是森林。树采用T表示。 10 | 11 | ## 有跟树 12 | 13 | 上面说树是没有方向的,但是如果我们在一个树中指定一个顶点为根,然后从这个根指向其他顶点作为方向时,就形成了有根树,即有向图。 14 | 15 | > 有跟树是指定一个顶点作为根并且每条边的方向都离开根的树。 16 | 17 | ![image-20210215211232937](https://tva1.sinaimg.cn/large/008eGmZEgy1gnoj1ff81jj30jt08tt8w.jpg) 18 | 19 | 比如上面的图所示。 20 | 21 | 再来拿下面这张图说明以下这些概念: 22 | 23 | ![image-20210215214014051](https://tva1.sinaimg.cn/large/008eGmZEgy1gnoju7weyoj30ed0ag3ys.jpg) 24 | 25 | 父母:即该点在根的方向的上一个点,比如c的父母是b。 26 | 27 | 孩子:即该点在根的方向的下几个点,比如g的孩子有h,i,j 28 | 29 | 兄弟:即该点的父母的除该点之外的点,比如h的兄弟有i和j 30 | 31 | 祖先们:从该点开始直到根为止经过的点,比如e的祖先有c,b,a 32 | 33 | 后代们:与祖先相对,从该点开始的所有点,比如b的后台有c,d,e 34 | 35 | 树叶:如果该点没有孩子,则该点称为树叶,比如d,e,f,k,i,l,m 36 | 37 | 内点:有孩子的点都可以称为内点,可以说树内除了树叶就是内点,比如a,b,g,c,h,j 38 | 39 | 子树:以某个点作为新的根,构建的更小的树,比如以g为根,构建的子树为 40 | 41 | ![image-20210215214935115](https://tva1.sinaimg.cn/large/008eGmZEgy1gnok3y3i8qj309v07h3yi.jpg) 42 | 43 | > 若有根树中每个内点的孩子数都小于m,则称该树为m叉树,若该树每个内点都恰好有m个孩子,则称它为满m叉树。 44 | > 45 | > 当m=2时,就是二叉树。 46 | 47 | ### 有序根树 48 | 49 | 就是规定了一个顶点的孩子的从左往右的顺序,比如下图所示: 50 | 51 | ![image-20210215220527457](https://tva1.sinaimg.cn/large/008eGmZEgy1gnokkgwcpvj30e009w74m.jpg) 52 | 53 | 在孩子中,左边的点都比右边的点小。 54 | 55 | 在二叉树中,左边的点叫做左子,右边的点叫做右子。以左子为根的子树叫做左子树,右子为根的子树叫做右子树。 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /11.1 树的概述:树的性质.md: -------------------------------------------------------------------------------- 1 | # 11.1 树的概述:树的性质 2 | 3 | > 带有n个顶点的树含有n-1条边 4 | 5 | 这个很容易理解,每2个顶点之间有1条边嘛。 6 | 7 | ------- 8 | 9 | > 带有i个内点的满m叉树含有n=mi+1个顶点 10 | 11 | [内点就是该顶点有孩子](https://blog.csdn.net/YQXLLWY/article/details/113820054) 12 | 13 | 这个证明很简单,因为是满m叉树,且有i个内点,所以边的总数为mi,然后结合上面的定理:n-1=mi,即n=mi+1。 14 | 15 | ------------ 16 | 17 | $$ 18 | 一个满m叉树若有:\\ 19 | \begin{cases} 20 | n个顶点,则有 i=\frac{n-1}{m}个内点和l=\frac{(m-1)\cdot n+1}{m} 个树叶 \\ 21 | i个内点,则有 n=mi+1个顶点和 l=(m-1)i+1个树叶\\ 22 | l个树叶,则有 n=\frac{ml-1}{m-1} 个顶点和 i=\frac{l-1}{m-1} 个内点 23 | \end{cases} 24 | $$ 25 | 26 | 前面两个结论就是套用上面的公式,就是第三个有点绕,这里解释一下: 27 | $$ 28 | \begin{cases} 29 | n=mi+1\\ 30 | n=l+i 31 | \end{cases} 32 | \\ 33 | 借用上面的公式得出:i=\frac{l-1}{m-1}\\ 34 | 再来求n,根据n=l+i=l+\frac{l-1}{m-1}=\frac{ml-1}{m-1} 35 | $$ 36 | 37 | ### 平衡的m叉树 38 | 39 | 这个书上的定义很奇怪啊: 40 | 41 | > 在每个顶点的子树读包含大约相同长度的通路。 42 | 43 | 层的概念: 44 | 45 | > 在有根树中顶点u的层是从根到这个顶点的唯一通路的长度。 46 | 47 | 然后就是有根树的高度: 48 | 49 | > 有根树的层高度就是顶点层数的最大值。 50 | 51 | 然后就是: 52 | $$ 53 | 在高度为h的m叉树中至多有 m^k 个树叶。\\ 54 | 即假设树叶数为l,则高度 h \geq \left\lceil \log_{m} l \right\rceil 55 | $$ 56 | 这个很好理解啊,最大值就是满m叉树嘛。 57 | 58 | -------------------------------------------------------------------------------- /11.2 树的应用:前缀码.md: -------------------------------------------------------------------------------- 1 | # 11.2 树的应用 2 | 3 | ## 前缀码 4 | 5 | 这玩意很有意思啊,假设我们用固定长度的5个byte位来表示26个英文字母,比如: 6 | 7 | - 00000:a 8 | - 00001:t 9 | 10 | 这样当我们想传递单词`at`的时候,就可以传输01的电信号`00000001`。但是接下来,试想有没有可能采用下面的形式来表示数据呢? 11 | 12 | ![image-20210216155752786](https://tva1.sinaimg.cn/large/008eGmZEgy1gnpfkazr28j30au0ck0sw.jpg) 13 | 14 | 即: 15 | 16 | - e的编码为:0 17 | - a的编码为:10 18 | - t的编码为:110 19 | - s的编码为:111 20 | 21 | 这样当我们想传输`teas`的时候,就可以传输 22 | 23 | | t | e | a | s | 24 | | ---- | ---- | ---- | ---- | 25 | | 110 | 0 | 10 | 111 | 26 | 27 | 即传输`110010111`。 28 | 29 | 这样带来的挑战是什么?就是我们没有办法按照固定长度来分割接收到的二进制数据,但是我们可以比照上面的那个二叉树,直到到达某一个树叶为止。 30 | 31 | 比如将上面的过程逆着来: 32 | 33 | ![image-20210216160817672](https://tva1.sinaimg.cn/large/008eGmZEgy1gnpfv6a4vcj30ke0cojrx.jpg) 34 | 35 | ![image-20210216160835010](https://tva1.sinaimg.cn/large/008eGmZEgy1gnpfvfk2llj30lz0cogm7.jpg) 36 | 37 | 然后像上面这种非固定长度的编码就是前缀码。 38 | 39 | ## 哈夫曼编码 40 | 41 | [参考B站视频](https://www.bilibili.com/video/BV1hK4y1k7Wr?from=search&seid=6506515302025619400) 42 | 43 | 上面是我们随意指定了编码的方式,现在我们需要先构建一颗树,然后再套用到上面的方式中。比如下面这句话: 44 | 45 | > To be,or not to be:that is the question 46 | 47 | 然后我们统计各个字符号出现的频率: 48 | 49 | - T : 0.03 50 | - o : 0.13 51 | - 空格: 0.18 52 | - b : 0.05 53 | - e : 0.1 54 | - , : 0.03 55 | - r : 0.03 56 | - n : 0.05 57 | - t : 0.15 58 | - : : 0.03 59 | - h : 0.05 60 | - a : 0.03 61 | - i : 0.05 62 | - s : 0.05 63 | - q : 0.03 64 | - u : 0.03 65 | 66 | 然后我们从中挑选最小的两个值,如果有很多最小的值也没关系,随便挑两个: 67 | 68 | ![image-20210216165705825](https://tva1.sinaimg.cn/large/008eGmZEgy1gnph9x01fjj309b04h3yg.jpg) 69 | 70 | 然后这里我们就可以把上面的`T`和`,(逗号)`去除掉了,加上一个新的频率值:0.06,然后再来挑2个最小值: 71 | 72 | ![image-20210216172740782](https://tva1.sinaimg.cn/large/008eGmZEgy1gnpi5r4esuj30cw09ejrk.jpg) 73 | 74 | 然后继续上面的步骤,直到完成下面这幅图: 75 | 76 | ![image-20210216172555706](https://tva1.sinaimg.cn/large/008eGmZEgy1gnpi3yhhlnj315a0k2dhv.jpg) 77 | 78 | 因为图片太大了,我估计缩小会糊,所以放一下[原图的地址](https://tva1.sinaimg.cn/large/008eGmZEgy1gnpi3yhhlnj315a0k2dhv.jpg) 79 | 80 | 这里说一下构建的方法,依次选择上面列表中最小的点,然后组建成新的顶点,就这样。构建好哈夫曼树之后,就可以套用到上面的二叉树编码中去了。 81 | 82 | ![image-20210216173536125](https://tva1.sinaimg.cn/large/008eGmZEgy1gnpidzyk5jj311v0iytas.jpg) 83 | 84 | [同样放一下原图地址](https://tva1.sinaimg.cn/large/008eGmZEgy1gnpidzyk5jj311v0iytas.jpg) 85 | 86 | 这样就可以得到例如`T`的编码就是:`00000`,`,`的编码就是`00001`。 87 | 88 | 这样的好处就是频率比较高的字符,比如`t`,它的编码就比较短`010`。 89 | 90 | 另外这里总数是1.02,而不是1是因为上面的数据是我用代码算出来的,精度上有点偏差。 91 | 92 | ### 哈夫曼树具体代码 93 | 94 | 这段代码真的是写死我了: 95 | 96 | ```php 97 | value=$value; 119 | $this->label=$label; 120 | } 121 | } 122 | 123 | /** 124 | * 将字符串转化成上面的类 125 | * @param $string 126 | * @return Leaf 127 | */ 128 | function prepareLeaves($string){ 129 | $length=strlen($string); 130 | $result=[]; 131 | for ($i=0;$i<$length;$i++){ 132 | $data=$string[$i]; 133 | !isset($result[$data]) && $result[$data]=0; 134 | $result[$data]++; 135 | } 136 | $prepare=false; 137 | $leaf=new Leaf(); 138 | foreach ($result as $word=>$count){ 139 | $value=round($count/$length,2); 140 | if (!$prepare){ 141 | $prepare=true; 142 | $leaf->value=$value; 143 | $leaf->label=$word; 144 | continue; 145 | } 146 | $newLeaf=new Leaf($value,$word); 147 | $leaf=sortLeaf($leaf,$newLeaf); 148 | } 149 | return $leaf; 150 | } 151 | 152 | /** 153 | * 构建哈夫曼树 154 | * @param $leaf Leaf 155 | */ 156 | function createHuffmanTree($leaf){ 157 | if (!$leaf->nextLeaf->nextLeaf){ 158 | $indexLeaf=new Leaf($leaf->value+$leaf->nextLeaf->value); 159 | $indexLeaf->leftLeaf=$leaf; 160 | $indexLeaf->rightLeaf=$leaf->nextLeaf; 161 | return $indexLeaf; 162 | } 163 | $newLeaf=new Leaf($leaf->value+$leaf->nextLeaf->value); 164 | $newLeaf->leftLeaf=$leaf; 165 | $newLeaf->rightLeaf=$leaf->nextLeaf; 166 | // 插入新的顶点并排序,保证最前面的2个一定是值最小的2个顶点 167 | $leaf=sortLeaf($leaf->nextLeaf->nextLeaf,$newLeaf); 168 | // 递归,并且之前用过的2个顶点不再继续使用 169 | return createHuffmanTree($leaf); 170 | } 171 | 172 | /** 173 | * 根据哈夫曼树在其中加上编码值 174 | * @param $leaf Leaf 175 | * @param string $preCode 176 | * @return bool 177 | */ 178 | function getWordCode($leaf,$preCode=''){ 179 | if (!$leaf){ 180 | return false; 181 | } 182 | if ($leaf->leftLeaf){ 183 | $leaf->leftLeaf->code=$preCode."0"; 184 | getWordCode($leaf->leftLeaf,$leaf->leftLeaf->code); 185 | } 186 | if ($leaf->rightLeaf){ 187 | $leaf->rightLeaf->code=$preCode."1"; 188 | getWordCode($leaf->rightLeaf,$leaf->rightLeaf->code); 189 | } 190 | } 191 | 192 | /** 193 | * 读取最终的编码值,保存在 result 数组中 194 | * @param $leaf Leaf 195 | * @param $result array 196 | * @return array 197 | */ 198 | function storeResult($leaf,&$result){ 199 | if (!$leaf){ 200 | return $result; 201 | } 202 | if ($leaf->label){ 203 | $result[$leaf->label]=$leaf->code; 204 | } 205 | storeResult($leaf->leftLeaf,$result); 206 | storeResult($leaf->rightLeaf,$result); 207 | } 208 | 209 | /** 210 | * 按照从小到大排序叶子节点 211 | * @param $leaf Leaf 212 | * @param $newLeaf Leaf 213 | * @return Leaf 214 | */ 215 | function sortLeaf($leaf,$newLeaf):Leaf{ 216 | if ($leaf->value>$newLeaf->value){ 217 | $newLeaf->nextLeaf=$leaf; 218 | return $newLeaf; 219 | } 220 | $thisLeaf=$leaf->nextLeaf; 221 | $lastLeaf=$leaf; 222 | if (!$thisLeaf){ 223 | $leaf->nextLeaf=$newLeaf; 224 | return $leaf; 225 | } 226 | while ($thisLeaf->nextLeaf && $thisLeaf->value<$newLeaf->value){ 227 | $lastLeaf=$thisLeaf; 228 | $thisLeaf=$thisLeaf->nextLeaf; 229 | } 230 | $lastLeaf->nextLeaf=$newLeaf; 231 | $newLeaf->nextLeaf=$thisLeaf; 232 | return $leaf; 233 | } 234 | ``` 235 | 236 | 上面是具体的操作代码,下面是调用: 237 | 238 | ```php 239 | 0 255 | [ ] => 100 256 | [n] => 10100 257 | [b] => 10101 258 | [i] => 10110 259 | [h] => 10111 260 | [e] => 1100 261 | [:] => 110100 262 | [r] => 110101 263 | [q] => 110110 264 | [a] => 110111 265 | [T] => 111000 266 | [u] => 111001 267 | [,] => 111010 268 | [s] => 111011 269 | [t] => 1111 270 | ) 271 | ``` 272 | 273 | 这里有个很有意思的地方,那就是`o`的编码是最短的,这个问题的答案我在代码中暂时没有找到原因,所以先搁置吧。 -------------------------------------------------------------------------------- /11.3 树的遍历.md: -------------------------------------------------------------------------------- 1 | # 11.3 树的遍历 2 | 3 | ## 通用地址信息 4 | 5 | 这玩意很简单,就是可以采用下面的形式标记树中每个点的位置: 6 | 7 | ![image-20210217165153703](https://tva1.sinaimg.cn/large/008eGmZEgy1gnqmqtqze4j30gc0cfaah.jpg) 8 | 9 | 就是类似上面这样的图一样。 10 | 11 | ## 前序遍历,后续遍历,后序遍历 12 | 13 | [参考B站视频](https://www.bilibili.com/video/BV1vv411t7mW?from=search&seid=13423928426148882137) 14 | 15 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnql5g87ovj30eq097tb7.jpg) 16 | 17 | ## 中缀,前缀和后缀记法 18 | 19 | 首先就是用二叉树来表示所需要进行的计算,比如式子:`(x+y)*2+(x-4)/3`可以用二叉树来表示: 20 | 21 | ![image-20210217162419208](https://tva1.sinaimg.cn/large/008eGmZEgy1gnqly69ph2j30kt0a5jro.jpg) 22 | 23 | ### 中缀记法 24 | 25 | 然后我们只需要对其进行中序遍历,就可以获得原来的式子了,但是为了跟原来的式子一致,我们还需要括号。 26 | 27 | 然后用这种方式获得的式子就是中缀记法。 28 | 29 | ### 前缀记法 / 波兰记法 30 | 31 | 在上面我们对上面的树采用中序遍历,这里改成前序遍历。这样得到的式子就是前缀记法。 32 | 33 | 根据这个式子进行计算时,我们必须要从**右到左**,如果遇到一个代表计算符号的字符,就计算该字符接下来的两个字符。比如当遇到`/-x43`时,从右到左,遇到`-`时,就计算`x-4`。 34 | 35 | ### 后缀记法 / 逆波兰记法 36 | 37 | 模仿上面的前缀记法,就是采用前序遍历。 38 | 39 | 然后根据这个式子计算时,采用从**左到右**,如果遇到一个代表计算符号的字符,就采用该符号计算该字符的前2个字符,比如遇到`xy+2+*`时,从左到右,当遇到`+`时,就计算`x+y`。 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /11.3 树的遍历:相关代码.md: -------------------------------------------------------------------------------- 1 | # 11.3 树的遍历:LDR,LRD,VLR 相关代码 2 | 3 | [基础定义介绍见这里](https://blog.csdn.net/YQXLLWY/article/details/113820054#comments_15041160) 4 | 5 | - VLR:前序遍历 6 | - LDR:中序遍历 7 | - LRD:后序遍历 8 | 9 | ```php 10 | label=$label; 19 | } 20 | } 21 | 22 | /** 23 | * 前序遍历 24 | * @param $leaf Leaf 25 | * @param string $result 26 | * @return bool 27 | */ 28 | function VLR($leaf,&$result){ 29 | if (!$leaf){ 30 | return false; 31 | } 32 | $result.=$leaf->label; 33 | VLR($leaf->leftLeaf,$result); 34 | VLR($leaf->rightLeaf,$result); 35 | } 36 | 37 | /** 38 | * 中序遍历 39 | * @param $leaf Leaf 40 | * @param $result string 41 | * @return bool 42 | */ 43 | function LDR($leaf,&$result){ 44 | if (!$leaf){ 45 | return false; 46 | } 47 | if ($leaf->leftLeaf){ 48 | LDR($leaf->leftLeaf,$result); 49 | } 50 | $result.=$leaf->label; 51 | LDR($leaf->rightLeaf,$result); 52 | } 53 | 54 | /** 55 | * 后续遍历 56 | * @param $leaf Leaf 57 | * @param $result string 58 | * @return bool 59 | */ 60 | function LRD($leaf,&$result){ 61 | if (!$leaf){ 62 | return false; 63 | } 64 | LRD($leaf->leftLeaf,$result); 65 | LRD($leaf->rightLeaf,$result); 66 | $result.=$leaf->label; 67 | return false; 68 | } 69 | 70 | // 相关记法部分 71 | 72 | /** 73 | * 解析前缀记法 74 | * @param $string 75 | * @return mixed 76 | */ 77 | function ParseStringVLR($string){ 78 | global $supportOperation; 79 | $stringIndex=strlen($string); 80 | $string=str_split($string); 81 | while ($stringIndex>0){ 82 | $stringIndex--; 83 | if (in_array($string[$stringIndex],$supportOperation)){ 84 | $string[$stringIndex]=calculate($string[$stringIndex],$string[$stringIndex+1],$string[$stringIndex+2]); 85 | unset($string[$stringIndex+1]); 86 | unset($string[$stringIndex+2]); 87 | $string=array_values($string); 88 | $stringIndex=count($string); 89 | } 90 | } 91 | return $string[0]; 92 | } 93 | 94 | /** 95 | * 解析后缀记法 96 | * @param $string 97 | * @return mixed 98 | */ 99 | function ParseStringLRD($string){ 100 | global $supportOperation; 101 | $length=strlen($string)-1; 102 | $string=str_split($string); 103 | $stringIndex=-1; 104 | while ($stringIndex<$length){ 105 | $stringIndex++; 106 | if (in_array($string[$stringIndex],$supportOperation)){ 107 | $string[$stringIndex]=calculate($string[$stringIndex],$string[$stringIndex-2],$string[$stringIndex-1]); 108 | unset($string[$stringIndex-1]); 109 | unset($string[$stringIndex-2]); 110 | $string=array_values($string); 111 | $length=count($string)-1; 112 | $stringIndex=0; 113 | } 114 | } 115 | return $string[0]; 116 | } 117 | 118 | /** 119 | * 解析中缀记法 120 | * @param $string 121 | * @return mixed 122 | */ 123 | function ParseStringLDR($string){ 124 | global $supportOperation; 125 | $length=strlen($string)-1; 126 | $string=str_split($string); 127 | $stringIndex=-1; 128 | while ($stringIndex<$length){ 129 | $stringIndex++; 130 | if (in_array($string[$stringIndex],$supportOperation)){ 131 | $string[$stringIndex]=calculate($string[$stringIndex],$string[$stringIndex-1],$string[$stringIndex+1]); 132 | unset($string[$stringIndex-1]); 133 | unset($string[$stringIndex+1]); 134 | $string=array_values($string); 135 | $length=count($string)-1; 136 | $stringIndex=0; 137 | } 138 | } 139 | return $string[0]; 140 | } 141 | 142 | $supportOperation=['+','-','*','/']; 143 | function calculate($operation,$data1,$data2){ 144 | $result=0; 145 | switch ($operation){ 146 | case "+": 147 | $result=$data1+$data2; 148 | break; 149 | case "-": 150 | $result=$data1-$data2; 151 | break; 152 | case "*": 153 | $result=$data1*$data2; 154 | break; 155 | case "/": 156 | if ($data2!=0){ 157 | $result=round($data1/$data2,2); 158 | } 159 | break; 160 | default: 161 | $result=0; 162 | } 163 | return $result; 164 | } 165 | ``` 166 | 167 | 然后这里是对应的调用代码: 168 | 169 | ```php 170 | leftLeaf=new Leaf('*'); 177 | $indexLeaf->rightLeaf=new Leaf('+'); 178 | $indexLeaf->leftLeaf->leftLeaf=new Leaf('+'); 179 | $indexLeaf->leftLeaf->leftLeaf->leftLeaf=new Leaf($x); 180 | $indexLeaf->leftLeaf->leftLeaf->rightLeaf=new Leaf($y); 181 | $indexLeaf->leftLeaf->rightLeaf=new Leaf(2); 182 | $indexLeaf->rightLeaf->leftLeaf=new Leaf('-'); 183 | $indexLeaf->rightLeaf->rightLeaf=new Leaf(3); 184 | $indexLeaf->rightLeaf->leftLeaf->leftLeaf=new Leaf($x); 185 | $indexLeaf->rightLeaf->leftLeaf->rightLeaf=new Leaf(4); 186 | return $indexLeaf; 187 | } 188 | 189 | $x=2; 190 | $y=4; 191 | $result=13; 192 | 193 | $indexLeaf=createLeaf($x,$y); 194 | $string=''; 195 | VLR($indexLeaf,$string); 196 | print $string.PHP_EOL; 197 | print ParseStringVLR($string).PHP_EOL; 198 | $string=''; 199 | LRD($indexLeaf,$string); 200 | print $string.PHP_EOL; 201 | print ParseStringLRD($string).PHP_EOL; 202 | $string=''; 203 | LDR($indexLeaf,$string); 204 | print $string.PHP_EOL; 205 | print ParseStringLDR($string); 206 | ``` 207 | 208 | 对应的树图如下所示: 209 | 210 | ![image-20210217205047500](https://tva1.sinaimg.cn/large/008eGmZEgy1gnqtne5mamj30q80cb3yz.jpg) 211 | 212 | 其中`x=2`,`y=4`。 -------------------------------------------------------------------------------- /11.4 树的应用:n皇后问题.md: -------------------------------------------------------------------------------- 1 | # 11.4 树的应用:n皇后问题 2 | 3 | 抛开西洋棋的规则,简单点就是,如果你在下面的图中放入一个棋子,则灰色部分都不能用了: 4 | 5 | ![image-20210218151415032](https://tva1.sinaimg.cn/large/008eGmZEgy1gnrpjkg3tsj307306j3ye.jpg) 6 | 7 | 即左右,对角线的空格都不能使用了,在这种情况下,问在`n*n`的格子中如何放置最多这样的黑色格子。 8 | 9 | 这里以`4*4`的格子为例: 10 | 11 | ![image-20210218151608512](https://tva1.sinaimg.cn/large/008eGmZEgy1gnrplj0thxj30sm06rjrb.jpg) 12 | 13 | 展示了一种摆法。 14 | 15 | 在这里要用到[深度优先搜索,也叫做回溯的算法来找](https://blog.csdn.net/YQXLLWY/article/details/113845073)。 16 | 17 | 首先说一下找的核心原理,就是从第1行开始找,找到一个合适的位置,比如`(0,0)`(数组下标是从0开始的)。 18 | 19 | ![image-20210218152151393](https://tva1.sinaimg.cn/large/008eGmZEgy1gnrprh3c1zj309k08djrb.jpg) 20 | 21 | 再来从第二列开始找合适的位置,结合上面的图我们就可以找到第二行合适的位置为`(2,1)`: 22 | 23 | ![image-20210218152316250](https://tva1.sinaimg.cn/large/008eGmZEgy1gnrpsxute2j308r085dfr.jpg) 24 | 25 | 但是在添加了`(2,1)`作为新的点之后: 26 | 27 | ![image-20210218152412801](https://tva1.sinaimg.cn/large/008eGmZEgy1gnrptxf1mtj308z080dfr.jpg) 28 | 29 | 导致下一行没有可以使用的位置了,所以我就就**回溯**到上一行,使用下一个可以使用的点: 30 | 31 | ![image-20210218152645608](https://tva1.sinaimg.cn/large/008eGmZEgy1gnrpwkgvafj308207q3yf.jpg) 32 | 33 | 这样再回到第3行,就还有一个位置可以使用。 34 | 35 | ![image-20210218152952240](https://tva1.sinaimg.cn/large/008eGmZEgy1gnrpztda4ej308907u0sn.jpg) 36 | 37 | 到这里就完成了使用回溯算法来实现n皇后问题了。 38 | 39 | 对应的代码: 40 | 41 | ```php 42 | =$mapLength){ 55 | return false; 56 | } 57 | // 获取下一个皇后的下标 58 | $columnIndex=getAvaliableNode($queens,$mapLength,$offset); 59 | // 递归到最后一行时,发现没有结果就停止,防止陷入死循环 60 | if (($rowIndex+1)==$mapLength && is_bool($columnIndex)){ 61 | return false; 62 | } 63 | // 正常获取到皇后的位置,则继续下一次递归 64 | if (!is_bool($columnIndex)){ 65 | $queens[$rowIndex]=$columnIndex; 66 | setQueen($queens,$mapLength,$rowIndex+1); 67 | }else{ 68 | // 没有获取到正确的皇后位置,回溯 & 重新开始获取值 69 | array_pop($queens); 70 | setQueen($queens,$mapLength,$rowIndex-1,$offset+1); 71 | } 72 | } 73 | 74 | /** 75 | * 计算下一个可以使用的空格下标 76 | * @param $queens array 已设定的点 77 | * @param $mapLength int n的值 78 | * @param int $offset 回溯时,跳过之前采用的点 79 | * @return false|int 80 | */ 81 | function getAvaliableNode($queens,$mapLength,$offset=0){ 82 | $nextRow=count($queens); 83 | $unavaliableColumnNumber=[]; 84 | foreach ($queens as $rowNumber=>$columnNumber){ 85 | // 计算该列不能使用 86 | $unavaliableColumnNumber[$columnNumber]=1; 87 | // 对角线不能使用 88 | $unavaliableColumnNumber[$columnNumber+($nextRow-$rowNumber)]=1; 89 | $unavaliableColumnNumber[$columnNumber-($nextRow-$rowNumber)]=1; 90 | } 91 | for ($i=0;$i<$mapLength;$i++){ 92 | if (!isset($unavaliableColumnNumber[$i])){ 93 | $offset--; 94 | if ($offset<0){ 95 | return $i; 96 | } 97 | } 98 | } 99 | return false; 100 | } 101 | 102 | $queens=[]; 103 | setQueen($queens,5); 104 | print_r($queens); 105 | ``` 106 | 107 | -------------------------------------------------------------------------------- /11.4 生成树.md: -------------------------------------------------------------------------------- 1 | # 11.4 生成树 2 | 3 | [图的基础知识](https://blog.csdn.net/YQXLLWY/article/details/113771353) 4 | 5 | > 设G是简单图。G的生成树是包含G的每个顶点的G的子图。 6 | 7 | 比如对于下面的左图,右图就是其生成树中的一种: 8 | 9 | ![image-20210218093527971](https://tva1.sinaimg.cn/large/008eGmZEgy1gnrfr0ujx8j30nz07c74k.jpg) 10 | 11 | 所以也可以说: 12 | 13 | > 简单图是连通的,当且仅当它有生成树。 14 | 15 | 这个概念可以类比到[哈赛图](https://blog.csdn.net/YQXLLWY/article/details/113732542),或者关系中的[传递性质](https://blog.csdn.net/YQXLLWY/article/details/113480886)。 16 | 17 | ## 深度优先搜索 / 回溯:DFS 18 | 19 | 之前还有一个[广度优先搜索](https://blog.csdn.net/YQXLLWY/article/details/113809623)的内容,用来找最短路径的。 20 | 21 | 这里深度优先搜索则是在一个简单图中构建生成树的方法。 22 | 23 | ![image-20210218101921334](https://tva1.sinaimg.cn/large/008eGmZEgy1gnrh0over2j30jp08egls.jpg) 24 | 25 | 比如上面这张图,假设以f作为根节点,然后开始构建。 26 | 27 | 首先就是顺着边走,走过的点不能重复走。 28 | 29 | 就可以得到下面的图片: 30 | 31 | ![image-20210218102234922](https://tva1.sinaimg.cn/large/008eGmZEgy1gnrh41tidaj30nz0gigm7.jpg) 32 | 33 | 然后从树叶的父母开始,将其作为根节点,重复上面的步骤: 34 | 35 | ![image-20210218103148655](https://tva1.sinaimg.cn/large/008eGmZEgy1gnrhdph8yfj30jf0h5t9e.jpg) 36 | 37 | 然后继续重复上面的步骤,就可以完成该简单图的生成树了。 38 | 39 | ![image-20210218103453517](https://tva1.sinaimg.cn/large/008eGmZEgy1gnrhguzbtsj30e508fwep.jpg) 40 | 41 | ## 宽度有限搜索 / 广度有限搜索:BFS 42 | 43 | [这个之前介绍过,可以看这里](https://blog.csdn.net/YQXLLWY/article/details/113809623) 44 | 45 | -------------------------------------------------------------------------------- /11.5 最小生成树.md: -------------------------------------------------------------------------------- 1 | # 11.5 最小生成树 2 | 3 | [生成树的基础概念见这里](https://blog.csdn.net/YQXLLWY/article/details/113842918) 4 | 5 | > 连通加权图里的最小生成树是具有边的权之和最小的生成树。 6 | 7 | 简单来说就是,首先这个图中每条边都有权重,而该图的生成树有很多种生成树,其中各个边权重加在一起最小的就是最小生成树。 8 | 9 | ## 普林算法 10 | 11 | [参考油管视频](https://www.youtube.com/watch?v=k7sYAs9J24w) 12 | 13 | 比如下面这张图。 14 | 15 | ![image-20210218215506401](https://tva1.sinaimg.cn/large/008eGmZEgy1gns14pjr5oj30dg0demxp.jpg) 16 | 17 | 随便选择一个点,比如选`g`,从`g`的边中选择一条权重最小的边。 18 | 19 | ![image-20210218215751870](https://tva1.sinaimg.cn/large/008eGmZEgy1gns17herjij30cv0cb0t9.jpg) 20 | 21 | 就是`g-d`,所以现在就从`{g,d}`的所有边中选择一个权重最低的,就是`d-e`。 22 | 23 | ![image-20210218215846954](https://tva1.sinaimg.cn/large/008eGmZEgy1gns18g227jj30eu0cljry.jpg) 24 | 25 | 接着重复上面的过程,应该是`g-e`,但是这样就会构成回路了,不符合生成树的定义,所以不能选,抛开这条之后就是`e-f`。重复上面的过程,就构成了最小生成树: 26 | 27 | ![image-20210218220349783](https://tva1.sinaimg.cn/large/008eGmZEgy1gns1dp5kgdj30cw0cr3z5.jpg) 28 | 29 | 这里撇清一个概念,就是[迪克斯特拉算法](https://blog.csdn.net/YQXLLWY/article/details/113809623),迪克斯特拉算法虽然是求加权图中两个点之间的权重最小值,但是不用包含每一个点,所以在这里不能拿来用。 30 | 31 | ## 克鲁斯卡尔算法 32 | 33 | [参考B站视频](https://www.bilibili.com/video/BV1Mf4y117bZ?from=search&seid=413211035918326469) 34 | 35 | 这个就更加简单了,首先还是下面这张图: 36 | 37 | ![image-20210218222359278](https://tva1.sinaimg.cn/large/008eGmZEgy1gns1ynvjbbj30c50d4mxo.jpg) 38 | 39 | 然后从中找出权值最小的一条边:`g-d`。 40 | 41 | ![image-20210218222448622](https://tva1.sinaimg.cn/large/008eGmZEgy1gns1zir4zgj30cw0czgm5.jpg) 42 | 43 | 然后再找剩下的权值最小的边:`e-d`。 44 | 45 | ![image-20210218222548010](https://tva1.sinaimg.cn/large/008eGmZEgy1gns20js0rsj30dq0cxaan.jpg) 46 | 47 | 48 | 49 | 继续寻找,从左到右就是过程,直到构建成下面这样: 50 | 51 | ![image-20210218222957851](https://tva1.sinaimg.cn/large/008eGmZEgy1gns24vs9ttj30ux0a73zo.jpg) 52 | 53 | 这个时候权重最小的边就是`g-e`,但是如果这条边也选上的话,就会构成回路,所以不能选择。遵照这样的规则,最终成果就是: 54 | 55 | ![image-20210218223120430](https://tva1.sinaimg.cn/large/008eGmZEgy1gns26ba8fwj309i09et90.jpg) 56 | 57 | 最终结果和上面是一样的。 -------------------------------------------------------------------------------- /12.1 布尔函数.md: -------------------------------------------------------------------------------- 1 | # 12.1 布尔函数 2 | 3 | 这个基本和[逻辑部分](https://blog.csdn.net/YQXLLWY/article/details/111086941)是类似的: 4 | $$ 5 | 补:\overline{1}=0,\overline{0}=1,就是逻辑关系中的 \neg \\ 6 | +,OR:1+1=1,1+0=1,0+0=0,就是逻辑中的 \wedge\\ 7 | \bullet,AND:1 \bullet 1=1,1 \bullet 0=0,0 \bullet 0=0,就是逻辑中的 \vee 8 | $$ 9 | 10 | ## 对偶性 11 | 12 | $$ 13 | 就是将 \cdot 替换成 +,将 + 替换成 \cdot,0替换成1,1替换成0。\\ 14 | 比如原式子:x \cdot (y+0),其对偶式就是 x+(y\cdot 1),化简成 x+y。 15 | 假设原布尔函数为 F,则其对偶函数表示为 F^d。 16 | $$ 17 | 18 | 这里对其做一下真值表: 19 | 20 | | x | y | x(y+0) | x+y | 21 | | ---- | ---- | ------ | ---- | 22 | | 0 | 0 | 0 | 0 | 23 | | 0 | 1 | 0 | 1 | 24 | | 1 | 0 | 0 | 1 | 25 | | 1 | 1 | 1 | 1 | 26 | 27 | 然后就是为了证明一个定理: 28 | $$ 29 | 假设两个布尔函数 F=G,则 F^d = G^d 30 | $$ 31 | 要证明这个定理,需要先证明下面这个定理: 32 | $$ 33 | 设F是一个含有变元 x_1,x_2,x_3 \cdots x_n 的布尔表达式。\overline{ F(\overline{x_1},\overline{x_2} \cdots \overline{x_n}) } = F^d (x_1,x_2,x_3 \cdots x_n) 34 | $$ 35 | 这个证明很简单: 36 | $$ 37 | 无论式子多复杂,都可以拆解成下面的几种形式:\\ 38 | \begin{cases} 39 | x+1\\ 40 | x+0\\ 41 | x\cdot 1\\ 42 | x \cdot 0\\ 43 | x \cdot y \\ 44 | x+y\\ 45 | \end{cases} 46 | \\ 47 | 然后就是这几个公式都是成立的:\\ 48 | \begin{cases} 49 | \overline{ \overline{x}+1 } &=0 &= x \cdot 0 \\ 50 | \overline{ \overline{x}+0 } &=x &=x \cdot 1 \\ 51 | \overline{ \overline{x} \cdot 1 } &=x &=x+0\\ 52 | \overline{ \overline{x} \cdot 0 } &=1 &=x+1\\ 53 | \overline{ \overline{x} \cdot \overline{y} } &= x+y \\ 54 | \overline{ \overline{x} + \overline{y} } &= x \cdot y 55 | \end{cases} 56 | $$ 57 | 最后两个式子用真值表来验证: 58 | 59 | | x | y | 第5个式子左侧 | 第5个式子右侧 | 第6个式子左侧 | 第6个式子右侧 | 60 | | ---- | ---- | ------------- | ------------- | ------------- | ------------- | 61 | | 0 | 0 | 0 | 0 | 0 | 0 | 62 | | 0 | 1 | 1 | 1 | 0 | 0 | 63 | | 1 | 0 | 1 | 1 | 0 | 0 | 64 | | 1 | 1 | 1 | 1 | 1 | 1 | 65 | 66 | 所以上面第二个结论是正确的。 67 | $$ 68 | 因为 \overline{ F(\overline{x_1},\overline{x_2} \cdots \overline{x_n}) } = F^d (x_1,x_2,x_3 \cdots x_n),\\ 69 | 所以 F(x_1,x_2,x_3 \cdots x_n)=\overline{ F^d (\overline{ x_1 },\overline{ x_2 },\overline{ x_3 } \cdots \overline{ x_n }) }\\ 70 | 所以 F=G,则 F^d = G^d 71 | $$ 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /12.2 布尔函数的表示.md: -------------------------------------------------------------------------------- 1 | # 12.2 布尔函数的表示 2 | 3 | ## 极小项 4 | 5 | 这个不用管那么多,其实就是所有变元做布尔积。比如3个布尔元x,y,z: 6 | 7 | | x | y | z | xyz | 8 | | ---- | ---- | ---- | ---- | 9 | | 0 | 0 | 0 | 0 | 10 | | 0 | 0 | 1 | 0 | 11 | | 0 | 1 | 0 | 0 | 12 | | 0 | 1 | 1 | 0 | 13 | | 1 | 0 | 0 | 0 | 14 | | 1 | 0 | 1 | 0 | 15 | | 1 | 1 | 0 | 0 | 16 | | 1 | 1 | 1 | 1 | 17 | 18 | 可以看到这种情况下,只有所有变元都是1,最终结果才为1,其他情况下都是0。 19 | 20 | ## 构建布尔函数 21 | 22 | 在之前都是如果知道布尔函数,可以通过定理来化简布尔函数,但是如果只知道真值表,如何构建布尔函数呢? 23 | 24 | 比如下面的真值表: 25 | 26 | | x | y | z | F | 27 | | ---- | ---- | ---- | ---- | 28 | | 1 | 1 | 1 | 0 | 29 | | 1 | 1 | 0 | 0 | 30 | | 1 | 0 | 1 | 1 | 31 | | 1 | 0 | 0 | 0 | 32 | | 0 | 1 | 1 | 0 | 33 | | 0 | 1 | 0 | 0 | 34 | | 0 | 0 | 1 | 0 | 35 | | 0 | 0 | 0 | 0 | 36 | 37 | 如何构建这个真值表的布尔函数呢? 38 | 39 | 这里就可以用上面的极小项来实现了,因为我们看到结果中只有一个值为1,其他情况下都是0。所以我们可以得出式子为: 40 | $$ 41 | F(x,y,z)=x \overline{y} z,这里为什么是 \overline{y} 呢?因为当时其值为0,所以需要处理一下。 42 | $$ 43 | 上面是有1个1,其他都是0,如果有2个1时: 44 | 45 | | x | y | z | G | 46 | | ---- | ---- | ---- | ---- | 47 | | 1 | 1 | 1 | 0 | 48 | | 1 | 1 | 0 | 0 | 49 | | 1 | 0 | 1 | 1 | 50 | | 1 | 0 | 0 | 0 | 51 | | 0 | 1 | 1 | 0 | 52 | | 0 | 1 | 0 | 1 | 53 | | 0 | 0 | 1 | 0 | 54 | | 0 | 0 | 0 | 0 | 55 | 56 | 我们就可以表示成2个极小项的和: 57 | $$ 58 | G(x,y,z)=x \overline{y}z+ \overline{x}y \overline{z} 59 | $$ 60 | 这样我们就可以根据真值表来构建布尔函数了。 61 | 62 | --------- 63 | 64 | 这样除了可以用来构建布尔函数,也可以用来化简布尔函数: 65 | $$ 66 | F(x,y,z)=(x+y) \overline{z} 67 | $$ 68 | 如果是之前,就需要按照公式一步步拆下去,现在可以首先计算出真值表为: 69 | 70 | | x | y | z | F | 71 | | ---- | ---- | ---- | ---- | 72 | | 1 | 1 | 1 | 0 | 73 | | 1 | 1 | 0 | 1 | 74 | | 1 | 0 | 1 | 0 | 75 | | 1 | 0 | 0 | 1 | 76 | | 0 | 1 | 1 | 0 | 77 | | 0 | 1 | 0 | 1 | 78 | | 0 | 0 | 1 | 0 | 79 | | 0 | 0 | 0 | 0 | 80 | 81 | 套用上面的公式,我们可以直接得出: 82 | $$ 83 | F(x,y,z)=xy \overline{z}+ x\overline{y} \overline{z}+\overline{x}y\overline{z} 84 | $$ 85 | 跟直接套公式得出的结论是一致的。 86 | 87 | ## 函数的完备性 88 | 89 | 上面我们得出,只需要使用`+,.,-`就可以构建出所有的布尔函数,但是根据下面的公式(德.摩根率): 90 | $$ 91 | \begin{cases} 92 | x+y &=\overline{ \overline{x}\overline{y} } \\ 93 | xy &=\overline{ \overline{x}+\overline{y} } 94 | \end{cases} 95 | $$ 96 | 所以我们只需要`+,-`或者`.,-`就可以构建所有的布尔函数了,这就是函数的完备性。 97 | 98 | 那么可以更小一点吗?也可以,我们定义一个运算符号:`|`,其真值表如下: 99 | 100 | | x | y | \| | 101 | | ---- | ---- | ---- | 102 | | 0 | 0 | 1 | 103 | | 0 | 1 | 1 | 104 | | 1 | 0 | 1 | 105 | | 1 | 1 | 0 | 106 | 107 | $$ 108 | 这样的情况下:\\ 109 | \begin{cases} 110 | \overline{x} &=x|x \\ 111 | xy &= (x|y)|(x|y) 112 | \end{cases} 113 | $$ 114 | 115 | 第二个式子可以用真值表来验证: 116 | 117 | | x | y | xy | (x\|y)\|(x\|y) | 118 | | ---- | ---- | ---- | -------------- | 119 | | 0 | 0 | 1 | 1 | 120 | | 0 | 1 | 1 | 1 | 121 | | 1 | 0 | 1 | 1 | 122 | | 1 | 1 | 0 | 0 | 123 | 124 | `|`也可以表示为`NAND`,就是*not and*,就是在布尔积的基础上取其补值。 125 | 126 | 类似的还有一个`NOR`,就是`not or`,就是在布尔和的基础上取其补值。 127 | $$ 128 | 表示为 \downarrow 129 | $$ 130 | 真值表为: 131 | 132 | | x | y | NOR | 133 | | ---- | ---- | ---- | 134 | | 0 | 0 | 1 | 135 | | 0 | 1 | 0 | 136 | | 1 | 0 | 0 | 137 | | 1 | 1 | 0 | 138 | 139 | 同时因为: 140 | $$ 141 | \begin{cases} 142 | \overline{x} &=x \downarrow x \\ 143 | x+y &= (x \downarrow y) \downarrow (x \downarrow y) 144 | \end{cases} 145 | $$ 146 | 所以可以说NAND和NOR也具有函数完备性。 -------------------------------------------------------------------------------- /12.4 电路的极小化.md: -------------------------------------------------------------------------------- 1 | # 12.4 电路的极小化 2 | 3 | 在之前[构建布尔函数](https://blog.csdn.net/YQXLLWY/article/details/114341750)部分,我们知道根据真值表我们可以写出所有的布尔函数,但是问题是这些布尔函数在电路实现上并不一定是最优价,比如: 4 | $$ 5 | F(x,y,z)=(x+y)\overline{z}=xy\overline{z}+x\overline{y}\overline{z}+\overline{x}y\overline{z} 6 | $$ 7 | 在拆开来之前,就只需要一个`+`,一个`-`,一个`.`,三个门就可以解决,结果拆开来之后,需要的操作数量多了很多,但是传统情况下,我们又是根据真值表来构建布尔函数的,现在的问题就是,在构建完布尔函数之后,如何简化其式子,实现减少操作步骤的过程,说人话就是如何根据上面拆开的式子去获得没有拆开前的式子。 8 | 9 | ## 卡诺图 10 | 11 | 这个就是其中一个工具。 12 | 13 | [参考视频](https://www.youtube.com/watch?v=gIjn3rK62RY&t=613s) 14 | 15 | 这里先开始最简单的,2个元素的卡诺图,假设真值表如下所示: 16 | 17 | | A | B | F | 18 | | ---- | ---- | ---- | 19 | | 0 | 0 | 1 | 20 | | 0 | 1 | 0 | 21 | | 1 | 0 | 1 | 22 | | 1 | 1 | 1 | 23 | 24 | 然后根据之前的知识,我们可以写出F的布尔函数为: 25 | $$ 26 | F(A,B)=\overline{A}\overline{B}+A\overline{B}+AB 27 | $$ 28 | 然后我们要化简上面的式子,就先构建下面这样的表格,把真值表中,为1的部分标进去: 29 | $$ 30 | 这里为了便于表示,就把 \overline{A}=a,\overline{B}=b 31 | $$ 32 | 33 | | | B | b | 34 | | ---- | ---- | ---- | 35 | | A | 1 | 1 | 36 | | a | | 1 | 37 | 38 | 然后我们就可以开始玩开心消消乐了: 39 | 40 | ![image-20210306185036160](https://tva1.sinaimg.cn/large/008eGmZEgy1goadpkg2j3j30wc03rdfr.jpg) 41 | 42 | 首先看红色部分,A和a都在其中,所以我们删除了`Ab`和`ab`,最终留下了`b`,然后再看绿色部分,我们删除了`AB`和`Ab`,最终留下了A,所以最终结果为: 43 | $$ 44 | F(A,B)=\overline{A}\overline{B}+A\overline{B}+AB=\overline{B}+A,\\ 45 | 下面为了验证,称F2(A,B)=\overline{B}+A 46 | $$ 47 | 这里我们用真值表验证一下: 48 | 49 | | A | B | F2 | 50 | | ---- | ---- | ---- | 51 | | 0 | 0 | 1 | 52 | | 0 | 1 | 0 | 53 | | 1 | 0 | 1 | 54 | | 1 | 1 | 1 | 55 | 56 | 结果和上面是一致的。PS,我不知道怎么证明卡诺图是有效的。 57 | 58 | 上面是最简单的卡诺图,下面来点复杂的: 59 | 60 | ![image-20210306190931852](https://tva1.sinaimg.cn/large/008eGmZEgy1goae99hux2j309u08lzka.jpg) 61 | 62 | 这里为了看的方便,然后开始开心消消乐: 63 | 64 | ![image-20210306233533775](https://tva1.sinaimg.cn/large/008eGmZEgy1goaly41e9pj30p508igly.jpg) 65 | 66 | 首先看第一张图,我们消除了`AB`和`aB`,所以剩下了`B`。 67 | 68 | 再来看第二张图,我们消除了`Cd`和`cd`,所以剩下了`d`,和上面剩下的`B`组成就是`Bc`。 69 | 70 | 再来看第三张图,我们消除了`cD`和`cd`,所以剩下了`c`,和上面剩下的`B`组成的就是`Bc`。 71 | $$ 72 | 所以最终的式子为:\\ 73 | F2(A,B,C,D)=B \overline{C}+B\overline{D} 74 | $$ 75 | 为了验证最终的结果,我们先还原原先的真值表: 76 | 77 | | A | B | C | D | F | 78 | | ---- | ---- | ---- | ---- | ---- | 79 | | 1 | 1 | 1 | 0 | 1 | 80 | | 0 | 1 | 1 | 0 | 1 | 81 | | 1 | 1 | 0 | 1 | 1 | 82 | | 0 | 1 | 0 | 1 | 1 | 83 | | 1 | 1 | 0 | 0 | 1 | 84 | | 0 | 1 | 0 | 0 | 1 | 85 | 86 | 然后就是我们推出来的式子的真值表,这里因为数据太多了,所以直接采用代码算了,代码贴在最下面: 87 | 88 | ```bash 89 | Array 90 | ( 91 | [0,0,0,0] => 0 92 | [1,0,0,0] => 0 93 | [0,1,0,0] => 1 // 94 | [1,1,0,0] => 1 // 95 | [0,0,1,0] => 0 96 | [1,0,1,0] => 0 97 | [0,1,1,0] => 1 // 98 | [1,1,1,0] => 1 // 99 | [0,0,0,1] => 0 100 | [1,0,0,1] => 0 101 | [0,1,0,1] => 1 // 102 | [1,1,0,1] => 1 // 103 | [0,0,1,1] => 0 104 | [1,0,1,1] => 0 105 | [0,1,1,1] => 0 106 | [1,1,1,1] => 0 107 | ) 108 | ``` 109 | 110 | 对比数据后发现结果是一致的。 111 | 112 | ### 计算采用的代码 113 | 114 | ```php 115 | $index){ 127 | $returnData[$line][$index]=$int[$key] ?? 0; 128 | } 129 | } 130 | return $returnData; 131 | } 132 | 133 | function F($map){ 134 | $returnData=[]; 135 | foreach ($map as $setting){ 136 | $result=$setting['B']*(1-$setting['C'])+$setting['B']*(1-$setting['D']); 137 | $result<0 && $result=0; 138 | $result>1 && $result=1; 139 | $returnData[implode(",",$setting)]=$result; 140 | } 141 | return $returnData; 142 | } 143 | 144 | print_r(F(createDefaultArray(4))); 145 | ``` 146 | 147 | ## 奎因-莫可拉基斯方法 148 | 149 | 直接上例子吧: 150 | $$ 151 | F(A,B,C)=ABC+A\overline{B}C+\overline{A}BC+\overline{A}\overline{B}C+\overline{A}\overline{B}\overline{C} 152 | $$ 153 | 先将式子拆分成下面的形式: 154 | 155 | |编号| 式子,就是上面的式子 | 比特串 | 156 | | ---- | ------ | ---- | 157 | |1| ABC | 111 | 158 | |2| AbC | 101 | 159 | |3| aBC | 011 | 160 | |4| abC | 001 | 161 | |5| abc | 000 | 162 | 163 | 然后如果是A,就是1,如果是a,就是0。B,C也是一样。 164 | 165 | 然后就是可以开始合并了,合并规则就是**两个比特串中只有1位不同**。 166 | 167 | 比如在这里,编号为1的`111`和编号2的`101`,就只有中间1位不同,所以可以合并。 168 | 169 | 然后就是编号为1的`111`和编号3的`011`,又只有第1位不同,所以可以合并。同理,编号2和4,编号3和编号4,编号4和编号5都可以合并。 170 | 171 | **合并后消掉的那一位,用-(减号)来表示**。 172 | 173 | | 编号 | 数据来源 | 合并后的式子所代表的比特串 | 174 | | ---- | -------- | -------------------------- | 175 | | a | 编号1和2 | 1-1 | 176 | | b | 编号1和3 | -11 | 177 | | c | 编号2和4 | -01 | 178 | | d | 编号3和4 | 0-1 | 179 | | e | 编号4和5 | 00- | 180 | 181 | 然后就是重复上面的步骤,这一步可以看到编号b和编号c可以合并,合并后结果位`--1`。然后`--1`可以和编号a的`1-1`合并,最终结果还是`--1`,接下来还可以和编号d合并,结果位`--1`,所以最终结果只剩下2个:`--1`和`00-`,所以最终的式子就是: 182 | $$ 183 | F(A,B,C)=C+\overline{A}\overline{B},即\\ 184 | F(A,B,C)=ABC+A\overline{B}C+\overline{A}BC+\overline{A}\overline{B}C+\overline{A}\overline{B}\overline{C}=C+\overline{A}\overline{B} 185 | $$ 186 | 然后用上面的代码改造一下验证结果是成立的。 187 | 188 | -------------------------------------------------------------------------------- /13.1 语言和文法.md: -------------------------------------------------------------------------------- 1 | # 13.1 语言和文法 2 | 3 | 这里刚开始名词有点多,一定要先理解这些名词才能往下看。 4 | 5 | 我们逐步拆分下面的定义啊: 6 | 7 | 1. 句子 8 | 2. 名词短语+动词短语 9 | 3. 冠词+形容词+名词+动词+副词 / 冠词+形容词+名词=名词短语,动词+副词=动词短语 10 | 4. the + 形容词+名词+动词+副词 / the 是冠词的其中一种 11 | 5. the + beautiful +名词+动词+副词 12 | 6. the + beautiful+lady+speak+loudly. 13 | 14 | 然后我们知道,仅仅以英文来说,是由24个英文字母+符号组成的,我们先定义一个概念:`V`,其包含所有组成语言的元素,所谓的句子,就是V中某些元素组成的子集合。 15 | 16 | 然后我们来看上面的第4句,其中the是否可以替换呢?不可以,因为the已经占了冠词的位置,那么`形容词`可以替换吗?可以,替换成一个真正的形容词,比如下面的`beautiful`就是替换后的结果。对于句子中能替换的元素,我们称为**非终结符**,记做`N`,不可以替换的,称为**终结符**,记做`T`。 17 | 18 | 然后如果有多个句子,我们如何标记一个句子的开头和结尾呢?为什么是开头而不是标记结尾呢?因为结尾符号太多了呀:感叹号,句号,问号,冒号等,所以标记一个句子的开头反而简单嘛,一个句子的开头符号我们记为`S`。 19 | 20 | 然后就是产生式:`P`,啥叫产生式呢?就是在上面中,我们说`the`可以替换掉`冠词`,就是一种替换规则,我们定义了 21 | $$ 22 | the \rightarrow 冠词 23 | $$ 24 | 再来就是定义派生的概念了,就是逐渐的用产生式来产生新的句子,比如我们从上面1派生出了2,再由2派生出了3等。 25 | 26 | 估计概念有点多,直接来一个例子: 27 | $$ 28 | 设 G=\{V,T,S,P\},V=\{a,b,A,B,S\},T=\{a,b\},P=\{S \rightarrow ABa,A \rightarrow BB,B \rightarrow ab,AB \rightarrow b \} \\ 29 | 根据上面的定义,我们可以由字符串 AB \rightarrow BBB,因为 A \rightarrow BB。同理,AB \rightarrow b。\\ 30 | 所有这些由S开始派生的,最终派生的由终结符构成的集合(即不可再派生)记做:L(G) 31 | $$ 32 | 比如上面的例子中: 33 | 34 | ![image-20210308221516058](https://tva1.sinaimg.cn/large/008eGmZEgy1gocuv4xp7fj30eu03awei.jpg) 35 | 36 | 然后我们就可以知道:`L(G)={abababa,ba}`。 37 | 38 | 下面的就更加玄乎了,但是我打算这样来讲: 39 | 40 | ### 1型文法 / 上下文有关文法 41 | 42 | ![image-20210308230020727](https://tva1.sinaimg.cn/large/008eGmZEgy1gocw644tezj30pz089gmg.jpg) 43 | 44 | 这种就是在上下文环境中,非终结符进行派生,也可以说非终结符被终结符包围。 45 | 46 | ### 2型文法 / 上下文无关文法 47 | 48 | ![image-20210308230244080](https://tva1.sinaimg.cn/large/008eGmZEgy1gocw8po0oej30r00bn3zu.jpg) 49 | 50 | 这种不需要管上下文,就是将非终结符进行派生,且派生后的字符串无法再派生。 51 | 52 | ### 3型文法 / 正则文法 53 | 54 | ![image-20210308231016897](https://tva1.sinaimg.cn/large/008eGmZEgy1gocwgggpo4j30qz0blwfr.jpg) 55 | 56 | 这个就是非终结符进行派生,派生后的结果中,还有非终结符,可以继续进行派生。 57 | 58 | ### 0型文法 59 | 60 | 没有任何限制,不过这个暂时也不用管。 61 | 62 | --- 63 | 64 | 然后在上面的文法中,如果派生之后的字符串长度小于大于等于派生前的长度,则称该文法为**非缔约的**,或者是**单调的**。 65 | 66 | ## 派生树 67 | 68 | [树的基础知识见这里](https://blog.csdn.net/YQXLLWY/article/details/113820054) 69 | 70 | 所谓派生树其实很简单,就是树的内点都是非终结符,树叶都是终结符: 71 | 72 | ![image-20210308232128208](https://tva1.sinaimg.cn/large/008eGmZEgy1gocws3cuqbj30bi09djro.jpg) 73 | 74 | 比如一开始举的例子。 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /13.2 带输出的有限状态机.md: -------------------------------------------------------------------------------- 1 | # 13.2 带输出的有限状态机 2 | 3 | -------------------------------------------------------------------------------- /4.4 求解同余方程.md: -------------------------------------------------------------------------------- 1 | # 4.4 求解同余方程 2 | 3 | #### 线性同余方程 4 | 5 | $$ 6 | ax \equiv b\ (mod\ m),其中,m \in {N}^{+},a,b \in N,x为变量,这样的方程称为线性同余方程 7 | $$ 8 | 9 | 首先,这是个方程,所以x是变量,剩下的就是在确定a,b,m的值之后,确定x的可选值有哪些。解题思路是这样的: 10 | $$ 11 | gcd(a,m)=1,且 a,m \in N,则必然存在一个数:\overline{a},称为a模m的逆,能够使得 a \cdot \overline{a} \equiv 1 (mod\ m)。 12 | $$ 13 | 这里先举一个现实的例子: 14 | $$ 15 | 假设 a=3,m=7,则 -2 \cdot 3 \equiv 1 (mod\ 7) 16 | $$ 17 | 在上面的基础之上,再来看下面的推论,让我们先假定这个逆一定存在(接下来会证明这个值一定存在)。这个值如何帮助我们解决最开始的问题呢? 18 | $$ 19 | \because ax \equiv b\ (mod\ m) \\ 20 | a \cdot \overline{a} \cdot x \equiv b \cdot \overline{a}\ (mod\ m) \\ 21 | a \cdot \overline{a} \cdot x\ mod\ m = ((a \cdot \overline{a}\ mod\ m) \times (x\ mod\ m))\ mod\ m \\ 22 | a \cdot \overline{a} \equiv 1\ (mod\ m) \\ 23 | x\ mod\ m = b \cdot \overline{a} \mod m \\ 24 | \therefore x \equiv b \cdot \overline{a}(\mod m) 25 | $$ 26 | 这样就能获得了x的表达式。 27 | 28 | 那么问题就来了: 29 | 30 | 1. a模m的逆一定存在吗? 31 | 2. 如果存在,如何计算呢? 32 | 33 | 先是证明这个值一定存在。 34 | $$ 35 | \because gcd(a,m)=1\\ 36 | \therefore \exists s,t,as+tm=1 \\ 37 | \therefore (as+tm) \equiv 1 (mod\ m) \\ 38 | (as+tm)(mod\ m)=((as\ mod\ m)+(tm\ mod\ m))\ mod\ m \\ 39 | \because tm\ mod\ m=0 \\ 40 | \therefore (as)\equiv 1 (mod\ m),这里s就是作为a的逆存在,因为s一定存在,所以 \overline{a} 一定存在 41 | $$ 42 | 接着就是这个值如何求,其实就是求[贝祖系数](https://blog.csdn.net/YQXLLWY/article/details/111502648) 43 | 44 | 比如这里的 45 | $$ 46 | 线性同余方程:3x \equiv 4\ (\mod 7) 的解是什么? 47 | $$ 48 | 解题过程: 49 | $$ 50 | \because 5 \cdot 3 - 2 \cdot 7=1 \\ 51 | \therefore x \equiv 5 \cdot 4 (\mod 7) \equiv 6 (\mod 7) 52 | $$ 53 | 当然,答案不止一个,因为 54 | $$ 55 | -8 \equiv 6(\mod 7),所以上面也可以写成 x \equiv -8 (\mod 7) 56 | $$ 57 | 58 | #### 中国剩余定理:多个同余方程组 59 | 60 | 上面介绍了一个线性方程组的解,但是如果有多个线性方程组的解需要整合时,该怎么处理呢? 61 | 62 | 比如: 63 | $$ 64 | x \equiv 2(\mod 3)\\ 65 | x \equiv 3(\mod 5)\\ 66 | x \equiv 2(\mod 7) 67 | $$ 68 | 问,这个时候如何求解? 69 | 70 | 暂时先不管上面的具体问题,我们把上面的方程组类比成下面的形式: 71 | $$ 72 | x \equiv {a}_{1}(\mod {m}_{1}) \\ 73 | x \equiv {a}_{2}(\mod {m}_{2}) \\ 74 | \vdots \\ 75 | x \equiv {a}_{n}(\mod {m}_{n}) \\ 76 | 且 gcd({m}_{i},{m}_{j})=1 77 | $$ 78 | 解: 79 | $$ 80 | 令 {M}_{k}=\frac{ 81 | {m}_{1} \times {m}_{1} \cdots {m}_{n} 82 | }{ 83 | {m}_{k} 84 | },令{y}_{k}为\ {y}_{k} \equiv {M}_{k} (\mod {m}_{k}),即 {y}_{k}为 {M}_{k}模{m}_{k}的逆 85 | \\ 86 | 则 x = {a}_{1}{M}_{1}{y}_{1}+{a}_{2}{M}_{2}{y}_{2} \cdots {a}_{n}{M}_{n}{y}_{n} 87 | $$ 88 | 首先说明为什么上面的这种解法有效: 89 | $$ 90 | \because 91 | ({a}_{1}{M}_{1}{y}_{1}+{a}_{2}{M}_{2}{y}_{2} \cdots {a}_{n}{M}_{n}{y}_{n})\ mod\ {m}_{j}= 92 | (({a}_{1}{M}_{1}{y}_{1} \mod {m}_{j})+({a}_{2}{M}_{2}{y}_{2} \mod {m}_{j}) \cdots ({a}_{n}{M}_{n}{y}_{n} \mod {m}_{j}))(mod\ {m}_{j}) \\ 93 | 当 n \neq j时,{M}_{n} \equiv 0 (\mod {m}_{j}),因为{M}_{n}中有{m}_{j},所以上面可以化简为 \\ 94 | {a}_{j}{M}_{j}{y}_{j} \mod {m}_{j} \\ 95 | 同时,(({a}_{j} \mod {m}_{j})({M}_{j}{y}_{j} \mod {m}_{j}))(mod\ {m}_{j}) 可以化简为 \\ 96 | {a}_{j} \mod {m}_{j} \\ 97 | \therefore x={a}_{j} \mod {m}_{j} 98 | $$ 99 | 然后上面可以得到一个x的值,但是我们看上面,我们可以得出,其实x可以写成 100 | $$ 101 | 令M=lcm({m}_{1},{m}_{2},{m}_{3} \cdots {m}_{n}),d=x mod M,则 \\ 102 | x=d\ (mod\ M) 103 | $$ 104 | 105 | 106 | [lcm,最小公倍数,定义见这里](https://blog.csdn.net/YQXLLWY/article/details/111502648) 107 | 108 | 具体例子见书上248页的例5. 109 | 110 | #### 大整数的计算机算术 111 | 112 | 这一章简单来说就是如何通过减少值来加快计算速度,比如让你计算1+3的速度总是快过10000+30000。说具体的计算方法前,书上的原话 113 | 114 | “ 115 | $$ 116 | m={m}_{1} \times {m}_{2} \cdots {m}_{n},且 gcd({m}_{i},{m}_{j})=1,\\ 117 | 则一个0<=a<=m的整数是否可以唯一表示成 (a\mod {m}_{1},a\mod {m}_{2},a\mod {m}_{3}, \cdots a\mod {m}_{n}) 118 | $$ 119 | ” 120 | 121 | 这样表示肯定没有问题的,因为在上面的中国剩余定理中我们证明了这样的数字是肯定存在的,至于在0~m之间是否唯一的问题了,在上面的最后我们也证明了这样的x的值是唯一的。 122 | 123 | 或者换个角度思考这个问题。 124 | 125 | ![](https://tva1.sinaimg.cn/large/0081Kckwgy1gm2iutvnv2j30gj0733ym.jpg) 126 | 127 | 这样的数字差一点都不行: 128 | 129 | ![](https://tva1.sinaimg.cn/large/0081Kckwgy1gm2iyaqgyjj30i005ht8o.jpg) 130 | 131 | 132 | 例子: 133 | 134 | > 将 123684和413456的加法转换成100内的加减 135 | 136 | $$ 137 | \because 这里选择100以内的4个数 99,98,97,95 \\ 138 | 123684 \mod 99=33 ,123684 \mod 98=8,123684 \mod 97=9,123684 \mod 95=89,所以将 123684 改写成 (33,98,97,95) \\ 139 | 同理 413456 改写成 (32,92,42,16) 140 | $$ 141 | 142 | 然后12368+413456可以归纳为 143 | $$ 144 | ((33+32)\mod 99,(98+92)\mod 98,(97+42)\mod 97,(95+16)\mod 95) \\ 145 | 即\\ 146 | (65,2,51,10) 147 | $$ 148 | 上面计算的原理见[这里的同余种的公式](https://blog.csdn.net/YQXLLWY/article/details/111425872) 149 | 150 | 然后如果要原始的值,需要计算 151 | $$ 152 | x \equiv 65 (mod\ 99) \\ 153 | x \equiv 2 (mod\ 98) \\ 154 | x \equiv 51 (mod\ 97) \\ 155 | x \equiv 10 (mod\ 95) 156 | $$ 157 | 这样的方式,可以加快计算速度,只有需要原来的值时,才需要进行100之外的计算。 158 | 159 | #### 费马小定理 160 | 161 | “ 162 | $$ 163 | 如果p为素数,且a \in N,a不能被p整除,则\\ 164 | {a}^{p-1} \equiv 1 (mod\ p),并且 \\ 165 | a^p \equiv a (mod\ p) 166 | $$ 167 | ” 168 | 169 | 证明: 170 | 171 | [二项式展示公式](https://baike.baidu.com/item/%E4%BA%8C%E9%A1%B9%E5%B1%95%E5%BC%80%E5%BC%8F/7078006?fr=aladdin) 172 | $$ 173 | a^p=(1+(a-1))^p= \\ 174 | \sum^{p}_{k=0} {C}^{k}_{p} {1}^{(p-k)} {(a-1)}^{k},{C}^{k}_{p}=\frac{p!}{(p-k)!k!}=\frac{p \cdot (p-1) \cdots (p-k+1)}{k!} \\ 175 | 其中因为 {C}^{k}_{p} \in N,所以 k!|(p \cdot (p-1) \cdots (p-k+1)),同时因为0 **数学归纳法原理:**为证明对所有的正整数n,p(n)为真,需要完成两个步骤: 4 | > 5 | > 基础步骤:P(1) 为真 6 | > 7 | > 归纳步骤:假设p(k)为真时,证明p(k+1)为真 8 | 9 | ## 实操 10 | 11 | $$ 12 | 使用数学归纳法证明:\\ 13 | P(n)=1+2+3 \cdots n=\frac{n(1+n)}{2} 14 | $$ 15 | 16 | 证明: 17 | $$ 18 | 基础步骤:n=1时,\frac{1\cdot(1+1)}{2}=1 \\ 19 | 归纳步骤:假设对于n=k时成立P(k)=\frac{k(k+1)}{2},对于P(k+1)=1+2+3 \cdots k+(k+1)\\ 20 | 因为 1+(k+1)=2+k=3+(k-1)=\cdots,所以当k为偶数时,p(k+1)=(k+1+1)*(\frac{k}{2})+(\frac{k}{2}+1)\\ 21 | =\frac{(k+1)(k+1+2)}{2}\\ 22 | 当k为奇数时,p(k+1)=(k+1+1)\frac{k+1}{2}=\frac{(k+1)(k+1+2)}{2}\\ 23 | 所以当p(k)为真时,P(k+1)也为真。 24 | $$ 25 | 26 | -------------------------------------------------------------------------------- /5.2 强归纳法和良序性.md: -------------------------------------------------------------------------------- 1 | # 5.2 强归纳法和良序性 2 | 3 | ## 强归纳法 4 | 5 | > 强归纳法:要证明对所有整数n而言,P(n)为真,需要完成如下两个步骤: 6 | > 7 | > 基础步骤:证明P(1)为真。 8 | > 9 | > 归纳步骤:假设对于不超过k的j而言,P(j)为真,那么P(k+1)也为真。 10 | 11 | #### 实操 12 | 13 | 采用强归纳法证明如果n是大于1的整数,则n可以写作素数之积。 14 | $$ 15 | 基础步骤:当n=2时,命题成立,2=1 \times 2 \\ 16 | 归纳步骤:假设对于大于1,小于k的整数,都可以写作素数之积。那么如果k+1是素数,很简单,k+1=1 \times (k+1),\\ 17 | 如果k+1是合数,则k+1可以写成两个小于k+1的正整数a和b的积(合数定义),则根据假设,a和b可以写成两个素数之积,\\ 18 | 即k+1可以写作素数之积。 19 | $$ 20 | 21 | ## 良序性公理 22 | 23 | > 任意一个非空的非负整数集合都有最小元素。 24 | 25 | -------------------------------------------------------------------------------- /5.3 递归定义与结构归纳法.md: -------------------------------------------------------------------------------- 1 | # 5.3 递归定义与结构归纳法 2 | 3 | ## 递归实操:树 4 | 5 | 树就是这样的东西 6 | 7 | ![](https://tva1.sinaimg.cn/large/0081Kckwgy1gmajj67pkqj30kg0asaat.jpg) 8 | 9 | #### 递归定义树 10 | 11 | 注意!是定义树,而不是创建树,如下面的图中所定义的: 12 | 13 | ![](https://tva1.sinaimg.cn/large/0081Kckwgy1gmajt5ervtj30c609c3yy.jpg) 14 | 15 | 如何采用递归找出其中所有的树? 16 | 17 | 基础步骤:定义树根,在这里定义为t0 18 | 19 | 递归步骤: 20 | 21 | #### 结构归纳法 22 | 23 | > - 基础步骤:证明对于递归定义的基础步骤所规定的属于该集合的所有元素来说,结果成立。 24 | > - 递归步骤:证明如果对于定义的递归步骤中用来构造新元素的每个元素来说命题为真,则对于这些新元素来说结果成立。 25 | 26 | -------------------------------------------------------------------------------- /5.4 递归算法.md: -------------------------------------------------------------------------------- 1 | # 5.4 递归算法 2 | 3 | > 若一个算法通过把问题归约到带更小输入的相同问题的实例来解决原来的问题,则这个算法称为递归的。 4 | 5 | 简单来所就是,将输入减小,比如下面这个阶乘的例子,求`n!`的值: 6 | 7 | ```php 8 | function factorial($n){ 9 | if ($n==1){ 10 | return 1; 11 | } 12 | return $n*factorial($n-1); 13 | } 14 | ``` 15 | 16 | 在上面的函数中,同一个函数,输入不断减小。 17 | 18 | ## 实操:归并排序 19 | 20 | 先说什么是归并排序,就是先将数组拆分成更小的数组,然后真对这些小数组进行排序,排序后组合成已经排好序的数组。 21 | 22 | 示意图 23 | 24 | ![](https://tva1.sinaimg.cn/large/0081Kckwgy1gmampk8pa4j30rw0l3q4n.jpg) 25 | 26 | 源代码 27 | 28 | ```php 29 | 假定一个过程可以被分解成前后两个任务,如果完成第一个任务有k种方法,在第一个任务之后的第二个任务有r种方法,那么完成这个任务的过程有k*r种方法。 6 | 7 | ```php 8 | $amount=[]; 9 | for ($k=1;$k<=100;$k++){ 10 | for ($r=1;$r<=100;$r++){ 11 | // 乘法法则 12 | $amount[]=$k*$r; 13 | } 14 | } 15 | print_r($amount); 16 | ``` 17 | 18 | #### 求和法则 19 | 20 | > 假定一个过程可以被分解成两个独立的任务,如果完成第一个任务有k种方法,第二个任务有r种方法,那么完成这个任务的过程有k+r种方法。 21 | 22 | ```php 23 | // 加法法则 24 | $amount=[]; 25 | for ($k=1;$k<=100;$k++){ 26 | $amount[]=$k; 27 | } 28 | for ($r=1;$r<=100;$r++){ 29 | $amount[]=$r; 30 | } 31 | print_r($amount); 32 | ``` 33 | 34 | #### 减法法则(两个集合的容斥原理) 35 | 36 | > 如果一个任务或者可以通过k种方法执行,或者可以通过r种另一类方法执行,则这个任务的方法数就是k+r后再减去两者的共同方法。 37 | 38 | ```php 39 | // 减法法则 40 | $amount=[]; 41 | for ($k=1;$k<=100;$k++){ 42 | $amount[$k]=1; 43 | } 44 | for ($r=50;$r<=150;$r++){ 45 | $amount[$r]=1; 46 | } 47 | print_r($amount); 48 | ``` 49 | 50 | #### 除法法则 51 | 52 | > 如果一个任务能由一个可以用n种方式完成的过程实现,而对于每种完成任务的方式w,在n种方法中恰好有d种与之对应,则完成这个任务的方法数为 n/d。 53 | 54 | ```php 55 | // 除法法则 56 | $amount=[]; 57 | $d=10; 58 | $result=0; 59 | for ($n=1;$n<=100;$n++){ 60 | if ($n % $d==0){ 61 | $amount[$n]=$result; 62 | $result++; 63 | continue; 64 | } 65 | $amount[$n]=$result; 66 | } 67 | 68 | print_r($amount); 69 | ``` 70 | 71 | #### 树图 72 | 73 | 其实这个很简单,就是以前说的把所有情况列出来。 74 | 75 | 比如,3位数的byte数能有多少种组合? 76 | 77 | ![](https://tva1.sinaimg.cn/large/0081Kckwgy1gmbzkucor8j30m809ijrv.jpg) 78 | 79 | 根据上面的图,从左到右可以得到值有: 80 | 81 | - 000 82 | - 001 83 | - 010 84 | - 011 85 | - 100 86 | - 101 87 | - 110 88 | - 111 89 | 90 | 共计8种组合方式。 -------------------------------------------------------------------------------- /6.2 鸽巢原理.md: -------------------------------------------------------------------------------- 1 | # 6.2 鸽巢原理 2 | 3 | > 鸽巢原理:如果k+1个或更多的物品放入k个盒子,那么至少有一个盒子包含了2个或更多的物体。 4 | 5 | 鸽巢原理也叫做狄利克雷抽屉原理。 6 | 7 | 这个很简单,比如现场有366人,那么至少有2个人的生日是同一天。 8 | 9 | > 推论1:一个从有k+1甚至更多的元素的集合到k个元素的集合的函数f不是一对一函数。 10 | 11 | [一对一函数的定义见这里](https://blog.csdn.net/YQXLLWY/article/details/111305452) 12 | 13 | > 广义鸽巢原理:如果N个物体放入k个盒子,那么至少有一个盒子包含了至少N/k个物体。 14 | 15 | 这个是在鸽巢原理的基础上,考虑了倍数的情况,还是上面的那个生日的例子,假设现在现场有365*2个人,那么至少有多少人的生日是相同的?2个。(我对闰年,非闰年不是很想算,所以懂意思就行。)在这个基础之上,3倍的时候呢?4倍的时候呢?最极端的情况就是每365个人,他们的生日都不是同一天,那么有N/k组,就有多少人的生日是一样的。 16 | 17 | #### 拉姆齐理论 18 | 19 | > 每个由n^2+1个不同实数构成的序列都包含一个长为n+1的严格递增或严格递减子序列。 20 | 21 | -------------------------------------------------------------------------------- /6.3 排列与组合.md: -------------------------------------------------------------------------------- 1 | # 6.3 排列与组合 2 | 3 | #### 排列 4 | 5 | > 具有n个不同元素的集合的r排列数是 6 | > 7 | > P(n,r)=n*(n-1)(n-2) ...... (n-r+1) 8 | 9 | 先解释一下这里的r的含义啊。就是要排列多少长度。比如P(10,3)就是10个元素排3个长度,那排列数自然是`10*9*8`,理解很简单,第一个位子有10个可选值,第二个有9个可选值,因为第一个位置已经使用掉了一个元素,同理,第三个位子有8个可选值。 10 | 11 | 下面这个推论你直接从数学公式推导的角度也可以看懂: 12 | $$ 13 | P(n,r)=\frac{n!}{(n-r)!} 14 | $$ 15 | 16 | #### 组合 17 | 18 | “ 19 | 20 | $$ 21 | 设n是正整数,r是满足 0<=r<=n 的整数,n元素的集合r组合数等于 \\ 22 | C(n,r)=\frac{n!}{r!(n-r)!} 23 | $$ 24 | ” 25 | 26 | r的含义和上面一样,选择的元素的个数。 27 | 28 | 排列和组合之间有什么区别呢?**顺序!!!**组合不讲究顺序,`{A,B,C}`和`{B,A,C}`在排列中是两个值,但是在组合中,是一个值。 29 | 30 | 那么上面那个公式怎么推倒出来呢? 31 | $$ 32 | C(n,r)=\frac{P(n,r)}{P(r,r)}=\frac{n!/(n-r)!}{r!/(r-r)!}\\ 33 | 上下同时乘以 (n-r)!\\ 34 | C(n,r)=\frac{n!}{r!(n-r)!} 35 | $$ 36 | 啥意思呢?这个理解起来比较绕。我们上面说了,组合是没有顺序的,但是如果不同的排列,落在另一个排列里,那就是组合。 37 | 38 | 比如r个元素的排列之后,再在其中放入不同元素,是不是就是组合了?所以先确定能放入数据的排列总数:P(n,r),接下来就是能放入的位置的排列:P(r,r),两者相除,就是组合的总数了。 39 | 40 | 下面是一个推论,把值代入到上面的公式中就能得到结果。 41 | $$ 42 | C(n,r)=C(n,n-r) 43 | $$ 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /6.4 二项式系数和恒等式.md: -------------------------------------------------------------------------------- 1 | # 6.4 二项式系数和恒等式 2 | 3 | $$ 4 | C(n,r) 可以记做\ \binom{n}{r},因为常出现在二项式展开式中作为系数,所以也叫做二项式系数。 5 | $$ 6 | 7 | #### 二项式定理 8 | 9 | $$ 10 | (x+y)^n=\sum^{n}_{j=0} \binom{n}{j} {x}^{n-j}{y}^{j}=\binom{n}{0} {x}^{n} + \binom{n}{1} {x}^{n-1}y+ \cdots + \binom{n}{1} x{y}^{n-1} + \binom{n}{n}{y}^{n} 11 | $$ 12 | 13 | 证明: 14 | $$ 15 | 基础步骤:当n=1时,上述结论正确。\\ 16 | 归纳步骤:假设当n时,结论成立。\\ 17 | 现在对于 {(x+y)}^{n+1}={(x+y)}^{n} \cdot (x+y)={(x+y)}^{n} \cdot x+{(x+y)}^{n} \cdot y\\ 18 | =\sum^{n}_{j=0} \binom{n}{j} {x}^{n+1-j}{y}^{j}+\sum^{n}_{j=0} \binom{n}{j} {x}^{n-j}{y}^{j+1}\\ 19 | =\sum^{n}_{j=0} \binom{n}{j} {x}^{n+1-j}{y}^{j}+\sum^{n}_{j=0} \binom{n}{j} {x}^{n-j}{y}^{j+1}\\ 20 | \\ 21 | 这里可以将其拆开来看一下\\ 22 | \sum^{n}_{j=0} \binom{n}{j} {x}^{n+1-j}{y}^{j}=\binom{n}{0}{x}^{n+1}+\binom{n}{1} {x}^{n}y+\binom{n}{2} {x}^{n-1}{y}^{2} \cdots +\binom{n}{n-1} x{y}^{n-1}+\binom{n}{n} x{y}^{n}\\ 23 | \sum^{n}_{j=0} \binom{n}{j} {x}^{n-j}{y}^{j+1}=\binom{n}{0} {x}^{n}y+\binom{n}{1} {x}^{n-1}{y}^{2} \cdots +\binom{n}{n-1} x{y}^{n}+ \binom{n}{n} {y}^{n+1} 24 | $$ 25 | 在这里插入一个公式:帕斯卡恒等式子([B站参考视频](https://www.bilibili.com/video/BV1TQ4y1P7Up?from=search&seid=9619760902590891781)),基本形式和证明如下: 26 | $$ 27 | C(m,k)+C(m,k-1)=C(m+1,k)\\ 28 | 证明:\\ 29 | \frac{m!}{(m-k)!k!}+\frac{m!}{(m-k+1)!k!}=\frac{m!(m-k+1)}{(m-k+1)!k!}+\frac{m!k}{(m-k+1)!k!}\\ 30 | = \frac{m!(m-k+1+k)}{(m-k+1)!k!}=\frac{(m+1)!}{(m+1-k)!k!}=C(m+1,k) 31 | $$ 32 | 33 | 34 | 接着上面的断掉的地方开始写 35 | $$ 36 | {(x+y)}^{n+1}=\binom{n}{0}{x}^{n+1}+\sum^{n}_{j=0}[\binom{n}{j}+\binom{n}{j+1}]{x}^{n-j}{y}^{j}+\binom{n}{0}{y}^{n+1}\\ 37 | ={x}^{n+1}+\sum^{n}_{j=0}\binom{n+1}{j+1}{x}^{n-j}{y}^{j}+{y}^{n+1}\\ 38 | =\binom{n+1}{0}{x}^{n+1}{y}^{0}+\sum^{n+1}_{j=1}\binom{n+1}{j+1}{x}^{n-j}{y}^{j}+\binom{n+1}{n+1}{x}^{0}{y}^{n+1}\\ 39 | =\sum^{n+1}_{j=0}\binom{n+1}{j} {x}^{n+1-j}{y}^{j} 40 | $$ 41 | 推论1: 42 | $$ 43 | \sum^{n}_{j=0} \binom{n}{j}=2^n \\ 44 | 证明:\\ 45 | \sum^{n}_{j=0} \binom{n}{j}({1}^{n-j}+1^j)=(1+1)^n=2^n 46 | $$ 47 | 推论2: 48 | $$ 49 | \sum^{n}_{j=0} \binom{n}{j} {(-1)}^{j}=0\\ 50 | 证明:\\ 51 | (1+(-1))^n=0=\sum^{n}_{j=0} \binom{n}{j}({{1}^{n-j}(-1)}^{j})=\sum^{n}_{j=0} \binom{n}{j} {(-1)}^{j} 52 | $$ 53 | 推论3: 54 | $$ 55 | \sum^{n}_{j=0} \binom{n}{j} {2}^{j}=3^n\\ 56 | 证明:\\ 57 | (1+2)^n=3^n =\sum^{n}_{j=0} \binom{n}{j} {2}^{j} 58 | $$ 59 | 60 | #### 范德蒙德恒等式 61 | 62 | $$ 63 | \binom{m+n}{r}=\sum^{r}_{k=0} \binom{m}{r-k} \binom{n}{k} 64 | $$ 65 | 66 | 书上给的证明我觉得很好,但是我还是更加相信数学推导,可是这块公式我推了半天没推成功,所以暂时搁置一下,说一下书上解释。 67 | 68 | > 如果你要从两个集合中取总数为r的组合,那么你可以选择: 69 | > 70 | > - 从第一个集合取0个,第二个集合取r个,那么就是 C(m,0)C(n,r) 71 | > 72 | > - 从第一个集合取1个,第二个集合取r-1个,那么就是 C(m,1)C(n,r-1) 73 | > - 从第一个集合取2个,第二个集合取r-2个,那么就是 C(m,2)C(n,r-2) 74 | > 75 | > 同理 76 | > 77 | > - 从第一个集合取r个,第二个集合取0个,那么就是 C(m,r)C(n,0) 78 | 79 | 将上面的公式总结起来就是上面的公式。 80 | 81 | 推论4: 82 | $$ 83 | 当 m=n 时\\ 84 | \binom{2n}{r}=\sum^{r}_{k=0} {\binom{n}{k}}^{2} 85 | $$ 86 | 推论5: 87 | $$ 88 | \binom{n+1}{r+1} = \sum^{n}_{j=r} \binom{j}{r} 89 | $$ 90 | 太累了,明天再想吧。 -------------------------------------------------------------------------------- /6.5 排列与组合的推广.md: -------------------------------------------------------------------------------- 1 | # 6.5 排列与组合的推广 2 | 3 | #### 有重复的排列 4 | 5 | > 当具有n个元素的集合允许重复的r位排列时,排列数是 n^r 6 | 7 | 比如以5个字母为总数的英语单词数量最多是:5^26 8 | 9 | #### 有重复的组合 10 | 11 | > 当具有n个元素的集合允许重复的r位组合时,组合总数是 C(n+r-1,r)=C(n+r-1,n-1) 12 | 13 | 这个怎么理解呢,当我们允许选择重复值时,其实就是在其中允许加入空值,这样的空值最多允许加入`(r-1)`位,因为全部的空值在之前的选项中有,如下图所示: 14 | 15 | 16 | 17 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gmij0pfb3vj30mi0eddg3.jpg) 18 | 19 | #### 部分重复的排列 20 | 21 | 简单来说就是不是所有值都可以重复,比如`Apple`这个单词有多少种排列方式,你就不能简单的用5^5来计算了,因为其中有重复项。 22 | 23 | > 设类型1的相同物体有n1个,类型2的相同物体有n2个。。。。。。类型k的相同物体有nk个,那么n个物体的不同排列数是 24 | 25 | $$ 26 | \frac{n!}{(n_1)!(n_2)! \cdots (n_k)!} 27 | $$ 28 | 29 | 证明: 30 | $$ 31 | 对类型1的物体,其有 C(n,n_1)种组合,\\ 32 | 对类型2的物体,其有 C(n-n_1,n_2)种组合,\\ 33 | \vdots \\ 34 | 对类型k的物体,其有 C(n-n_1-n_2-n_3 \cdots -{n}_{n_k-1},n_k)种组合 \\ 35 | 所以总共的排列总数是\\ 36 | C(n,n_1) \cdot C(n-n_1,n_2) \cdots C(n-n_1-n_2-n_3 \cdots -{n}_{n_k-1},n_k) \\ 37 | = \frac{n!}{(n-n_1)!{n}_{1}!} \cdot \frac{(n-n_1)!}{(n-n_1-n_2)!{n}_{2}!} \cdots \\ 38 | = \frac{n!}{(n_1)!(n_2)! \cdots (n_k)!} 39 | $$ 40 | 41 | ## 变形 42 | 43 | #### 可辨别的物体与可辨别的盒子 44 | 45 | 例如,把52张牌,分给4个人,每个人5张牌,问有多少种方式。这个问题和上面部分重复的排列是一样的。只是有一点,那就是最后需要剩下32张牌,即最后一个类型的值是32. 46 | 47 | “ 48 | $$ 49 | 把n个不同的物体分配到k个不同的盒子使得n_i个物体放入盒子i的方式数等于\\ 50 | \frac{n!}{(n_1)!(n_2)! \cdots (n_k)!} 51 | $$ 52 | ” 53 | 54 | #### 不可辨别的物体与可辨别的盒子 55 | 56 | 这个啥意思呢?比如将相同的10个小球放入编号1-8的桶中,共有多少种放法,是不是就是上面的有重复的组合,所以结论就是: 57 | $$ 58 | C(10+8-1,8) 59 | $$ 60 | 61 | #### 可辨别的物体与不可辨别的盒子 62 | 63 | 这个比较麻烦,那就是将10个不同的小球,放到4个相同的桶中,共有多少种放法。 64 | 65 | 这个等到《第八章:高级计数》的时候再去介绍。 66 | 67 | #### 不可辨别的物体和不可辨别的盒子 68 | 69 | 这个就是将10个相同的小球,放到4个相同的桶中,共有多少种放法。 70 | 71 | 这个换一种问法就是10可以拆分成多少种4个数的加法,暂时好像只有列举法: 72 | 73 | - 10=10+0+0+0 74 | - 10=1+9+0+0 75 | - 10=1+8+1+0 76 | - ...... 77 | 78 | -------------------------------------------------------------------------------- /7.1 离散概率引论.md: -------------------------------------------------------------------------------- 1 | # 7.1 离散概率引论 2 | 3 | $$ 4 | 事件E是结果具有相等可能性的有限样本空间S的子集,则事件E的概率是:\\ 5 | p(E)=\frac{|E|}{|S|} 6 | $$ 7 | 8 | ------------------------ 9 | 10 | $$ 11 | 事件E是样本空间S的一个事件。事件 \overline{E}=S-E(事件E的补事件)的概率是:\\ 12 | \overline{E}=S-E 13 | $$ 14 | 15 | ------------------------ 16 | 17 | $$ 18 | 事件E_1和E_2是样本空间的事件,那么\\ 19 | P(E_1 \cup E_2)=P(E_1)+P(E_2)-P(E_1 \cap E_2) 20 | $$ 21 | 22 | -------------------------------------------------------------------------------- /7.2 概率论.md: -------------------------------------------------------------------------------- 1 | # 7.2 概率论 2 | 3 | “ 4 | $$ 5 | 假设S是n个元素的集合,均匀分布赋给S中的每个元素的概率是 \frac{1}{n} 6 | $$ 7 | 8 | ------------ 9 | 10 | $$ 11 | 事件E的概率是在E中结果的概率之和,即\\ 12 | p(E)=\sum_{s \in E}p(s) 13 | $$ 14 | 15 | ” 16 | 17 | ----------- 18 | 19 | " 20 | $$ 21 | 如果E_1,E_2 \cdots E_n 是样本空间S中两两不交事件的序列,那么\\ 22 | p(\bigcup_{i} E_i )=\sum_{i} p(E_i) 23 | $$ 24 | " 25 | 26 | 注意这里是各个事件都是不相交的,且在同一个样本空间中,如果相交,则需要[参考这里的公式](https://blog.csdn.net/YQXLLWY/article/details/112594361) 27 | 28 | --------------- 29 | 30 | “ 31 | $$ 32 | 设E和F是具有p(F)>0的事件,给定F的条件下E的条件概率记做p(E|F),定义为\\ 33 | p(E|F)=\frac{p(E \cap F)}{p(F)} 34 | $$ 35 | ” 36 | 37 | 这里举书上的一个例子来说比较好: 38 | 39 | 假设4位0,1组成的字符串,当第一个位0的情况下,结果中出现2个连续的0的概率有多少? 40 | $$ 41 | F:第一位为0 \\ 42 | E:结果中出现2个连续的0\\ 43 | E \cap F=\{0000,0001,0010,0011\}\\ 44 | F:\{0000,0001,0010,0011,0100,0101,0110,0111\}\\ 45 | 样本总个数为 2^4=16,所以\\ 46 | p(E \cap F)=\frac{4}{16} \\ 47 | p(F)=\frac{8}{16}\\ 48 | 所以 p(E|F)=\frac{4}{8}=\frac{1}{2} 49 | $$ 50 | 有没有觉得其实就是在F的样本集中找E的样本集? 51 | 52 | ---------------- 53 | 54 | “ 55 | $$ 56 | 事件E和F是独立的,当且仅当 p(E \cap F)=p(E) \cdot p(F) 57 | $$ 58 | ” 59 | 60 | 注意这里和上面的不同之处在于上面是在同一个样本集中考虑的,而这里则是在两个样本集中考虑的。 61 | 62 | -------------- 63 | 64 | ### 伯努利试验与二项分布 65 | 66 | $$ 67 | 在n次独立的伯努利试验中有k次成功的概率在成功概率为p,失败概率为q=1-p时,概率为\\ 68 | b(k;n,p)=C(n,k){p}^{k}{q}^{n-k} 69 | $$ 70 | 71 | 先介绍啥叫伯努利试验,就是结果只有2种的试验,2种试验结果的概率不一定要一致。再来就是上面的那个公式叫做**二项分布**。 72 | 73 | 这里借用书上的一个例子说明一下: 74 | 75 | 投掷一次硬币,出现人头和画的概率各是1/2,问出现4次人头的概率是多少? 76 | $$ 77 | 首先,在总数为n的伯努利试验中,进行k次概率为p的试验,其每次的概率为\\ 78 | {p}^{k}{q}^{n-k}\\ 79 | 在上面的例子中就是 {(\frac{1}{2})}^{4} \cdot {(\frac{1}{2})}^{3}\\ 80 | 其结果总数为 C(7,4)=\frac{7!}{3!4!}=35\\ 81 | 所以概率是 C(7,4) \cdot {(\frac{1}{2})}^{4} \cdot {(\frac{1}{2})}^{3}=\frac{35}{128} 82 | $$ 83 | -------------------------------------------------------------------------------- /7.3 贝叶斯定理.md: -------------------------------------------------------------------------------- 1 | # 7.3 贝叶斯定理 2 | 3 | $$ 4 | 在之前我们知道:p(E|F)=\frac{P(E \cap F)}{p(F)}\\ 5 | 但是如果我们知道:p(E|F),p(E|\overline{F}),p(F),那么我们就可以知道p(F|E) 6 | $$ 7 | 8 | 证明: 9 | $$ 10 | 因为:\\ 11 | p(E|F)=\frac{p(E \cap F)}{p(F)}\\ 12 | p(E|\overline{F})=\frac{p(E \cap \overline{F})}{p(\overline{F})}\\ 13 | p(E)=p(E|F)\cdot p(F)+p(E|\overline{F}) \cdot p(\overline{F}) \\ 14 | 所以:\\ 15 | p(F|E)=\frac{p(F|E)}{p(E)}\\ 16 | =\frac{p(F \cap E)}{p(E|F)\cdot p(F)+p(E|\overline{F}) \cdot p(\overline{F})}\\ 17 | =\frac{p(E \cap F)}{p(E|F)\cdot p(F)+p(E|\overline{F}) \cdot p(\overline{F})}\\ 18 | =\frac{p(E|F) \cdot p(F)}{p(E|F)\cdot p(F)+p(E|\overline{F}) \cdot p(\overline{F})} 19 | $$ 20 | 举个例子就是: 21 | 22 | - E:得癌症死亡 23 | - F:确诊癌症 24 | - p(E|F):确诊癌症后死亡 25 | - p(E|-F):没有确诊癌症却得癌症后死亡 26 | - p(F|E):在确定癌症死亡律后,当自己确诊癌症时,自己有多少概率死亡 27 | 28 | [p(E|F)得定义见这里](https://blog.csdn.net/YQXLLWY/article/details/112596797) 29 | 30 | 在之前说过,p(E|F)其实像是在p(F)中找p(E n F)的数量。在上面的:p(F|E),其实也可以理解,在得癌症死亡的人数中,多少人是确诊的。那么p(E|F)和p(F|E)是相等的吗? 31 | 32 | 不是,因为基数不同,p(E|F)是以确诊人数为基数,其中的死亡人数。p(F|E),则是以死亡人数为基数,其中确诊的人数。 33 | 34 | 最后就是上面的这个公式: 35 | $$ 36 | p(E)=p(E|F)\cdot p(F)+p(E|\overline{F}) \cdot p(\overline{F})\\ 37 | =p(E \cap F)+p(E \cap \overline{F}) 38 | $$ 39 | 这个可以这么理解:得癌症死亡的人=被确诊癌症并且得癌症死亡的人+没有确诊癌症但是得癌症死亡的人 40 | 41 | 同时还有一个问题,那就是: 42 | $$ 43 | 1-p(E|F)=p(\overline{E}|F) 44 | $$ 45 | 46 | ### 拓展的贝叶斯定理 47 | 48 | 上面只有2种情况: 49 | $$ 50 | F 和 \overline{F} 51 | $$ 52 | 但是如果有多种情况呢?比如F1,F2,F3,F4等。 53 | $$ 54 | p(E)=p(E|F_1)\cdot p(F_1)+p(E|F_2)\cdot p(F_2)+p(E|F_3)\cdot p(F_3) \cdots p(E|F_n)\cdot p(F_n) \\ 55 | 且\\ 56 | \bigcup^{n}_{i=1} F_i=S \\ 57 | 那么\\ 58 | p(F_j | E)=\frac{p(E|F_j) \cdot p(F_j)}{\sum^{n}_{i} (p(E|F_i)\cdot p(F_i))} 59 | $$ 60 | 61 | 62 | -------------------------------------------------------------------------------- /7.4 期望值和方差.md: -------------------------------------------------------------------------------- 1 | # 7.4 期望值和方差 2 | 3 | ## 期望值 4 | 5 | $$ 6 | E(X)=\sum_{s \in S}p(s)X(s) 7 | $$ 8 | 9 | 例如一个点数从1到6的骰子,其投掷一次的期望值是 10 | $$ 11 | E(X)=1 \cdot \frac{1}{6}+2 \cdot \frac{1}{6}+3 \cdot \frac{1}{6}+4 \cdot \frac{1}{6}+5 \cdot \frac{1}{6}+6 \cdot \frac{1}{6} 12 | $$ 13 | 不用神话期望值,其本质就是对应的值乘以概率的和,所有的值要布满样本空间。 14 | 15 | ----------- 16 | 17 | #### 随机变量与期望值 18 | 19 | 随机变量这个词比较迷惑性,可能是英译中的时候搞出来的,所以这里可以将其理解为函数。 20 | 21 | 将原本的样本空间中的字集经过函数处理后所得到的值,比如掷两个骰子,两个骰子的和。原本的样本空间和其所对应的函数处理结果如下所示,函数使用X表示: 22 | 23 | ```mathematica 24 | X((1,1))=2 25 | X((1,2))=X((2,1))=3 26 | X((1,3))=X((3,1))=X((2,2))=4 27 | X((1,4))=X((4,1))=X((2,3))=X((3,2))=5 28 | X((1,5))=X((5,1))=X((2,4))=X((4,2))=X((3,3))=6 29 | X((1,6))=X((6,1))=X((2,5))=X((5,2))=X((3,4))=X((4,3))=7 30 | X((2,6))=X((6,2))=X((3,5))=X((5,3))=X((4,4))=8 31 | X((3,6))=X((6,3))=X((4,5))=X((5,4))=9 32 | X((4,6))=X((6,4))=X((5,5))=10 33 | X((5,6))=X((6,5))=11 34 | X((6,6))=12 35 | ``` 36 | 37 | 其中原本的样本空间`(1,1),(1,2),(2,1)`经过函数处理后,构成了X的样本空间`X(S)`。 38 | $$ 39 | (r,p(X=r)),代表r \in X(S),p(X=r)代表X=r的概率。 40 | $$ 41 | 42 | 在上面的基础上,问投出的值的概率各是多少? 43 | 44 | ```mathematica 45 | p(X=2)=p(X=12)=1/36 46 | p(X=3)=p(X=11)=2/36 47 | p(X=4)=p(X=10)=3/36 48 | p(X=5)=p(X=9)=4/36 49 | p(X=6)=p(x=8)=5/36 50 | p(X=7)=6/36 51 | ``` 52 | 53 | 这里的`p(X=2)`代表上面两个骰子的和为2的情况,看到只有1种,`X((1,1))`,`p(X=12)`同理,`X((6,6))`。 54 | 55 | **随机变量其实本质就是在之前所有样本空间的基础上,使用函数,修改p(X=r)时,r的值。** 56 | 57 | 投出的值的期望值的计算就按照期望值的定义走就行了: 58 | $$ 59 | E(X)=2 \cdot \frac{1}{36}+3 \cdot \frac{2}{36}+ 4 \cdot \frac{3}{36}+ 5 \cdot \frac{4}{36}+6 \cdot \frac{5}{36}+7 \cdot \frac{6}{36}\\ 60 | +12 \cdot \frac{1}{36}+11 \cdot \frac{2}{36}+ 10 \cdot \frac{3}{36}+ 9 \cdot \frac{4}{36}+8 \cdot \frac{5}{36} \\ 61 | =7 62 | $$ 63 | 64 | #### 期望值的线性性质 65 | 66 | 在确定结果的情况下,可不可以试试单独计算两个骰子的期望值,然后相加呢? 67 | $$ 68 | E(X_1)=1 \cdot \frac{1}{6}+2 \cdot \frac{1}{6}+3 \cdot \frac{1}{6}+4 \cdot \frac{1}{6}+5 \cdot \frac{1}{6}+6 \cdot \frac{1}{6}=\frac{7}{2}\\ 69 | E(X_2)=1 \cdot \frac{1}{6}+2 \cdot \frac{1}{6}+3 \cdot \frac{1}{6}+4 \cdot \frac{1}{6}+5 \cdot \frac{1}{6}+6 \cdot \frac{1}{6}=\frac{7}{2}\\ 70 | E(X_1)+E(X_2)=\frac{7}{2}+\frac{7}{2}=7 71 | $$ 72 | 结果竟然一致,书上是通过[数学归纳法](https://blog.csdn.net/YQXLLWY/article/details/112106627)证明的,但是我在这里就写一下结论 73 | 74 | $$ 75 | 如果 X_i 是 S 上的随机变量,n是正整数,并且 a,b \in N,\\ 76 | E(X_1+X_2+X_3 \cdots X_n)=E(X_1)+E(X_2)+E(X_3) \cdots E(X_n)\\ 77 | E(a \cdot X+b)=a \cdot E(X)+b 78 | $$ 79 | 80 | ---------- 81 | 82 | > n次试验的伯努利试验的期望值是 np,其中p是每次试验的中“成功”的概率 83 | 84 | [伯努利试验就是试验结果只有2种的事件](https://blog.csdn.net/YQXLLWY/article/details/112596797) 85 | 86 | 在开始证明前,先证明一个推论: 87 | $$ 88 | C(n,k) \cdot k=nC(n-1,k-1)\\ 89 | 证明:\\ 90 | C(n,k) \cdot k=\frac{n!}{(n-k)!k!} \cdot k= \frac{n \cdot (n-1!)}{((n-1)-(k-1))!(k-1)!k} \cdot k= n \frac{(n-1)!}{((n-1)-(k-1))!(k-1)!}=n C(n-1,k-1) 91 | $$ 92 | 93 | 94 | [C(n,k)就是总数为n的k个样本的组合总数](https://blog.csdn.net/YQXLLWY/article/details/112427740) 95 | 96 | 证明: 97 | $$ 98 | E(X)=\sum^{n}_{k=1}k \cdot p(k)\\ 99 | =\sum^{n}_{k=1} k \cdot C(n,k) p^k {q}^{(n-k)} \\ 100 | =\sum^{n}_{k=1} n \cdot c(n-1,k-1) p^k {q}^{(n-k)}\\ 101 | =np \sum^{n}_{k=1} c(n-1,k-1) {p}^{k-1} {q}^{n-k} \\ 102 | 令 j=k-1 \\ 103 | =np \sum^{n}_{k=1} c(n-1,k-1) {p}^{k-1} {q}^{n-k} \\ 104 | =np \sum^{n-1}_{j=0} c(n-1,j) {p}^{j} {q}^{n-(j+1)} \\ 105 | =np \sum^{n-1}_{j=0} c(n-1,j) {p}^{j} {q}^{n-1-j} \\ 106 | =np {(p+q)}^{n-1}=np 107 | $$ 108 | 其中倒数第二步是因为[二项式定理](https://blog.csdn.net/YQXLLWY/article/details/112417453) 109 | 110 | 在算法的角度看,**期望值其实就是平均算法复杂度**。但是我看了很久,没有弄懂,所以暂时不深究了。 111 | 112 | #### 几何分布 113 | 114 | 这个证明很鬼扯,但是结论却很简单,所以直接上结论: 115 | $$ 116 | 如果对于k=1,2,3,4 \cdots n,p(X=k)={(1-p)}^{(k-1)} \cdot p,那么随机变量X具有带参数p的几何分布。 117 | $$ 118 | 比如投掷骰子,问第n次出现6的概率是多少时: 119 | 120 | ```mathematica 121 | p(X=1)=1/6 122 | p(X=2)=5/6 * 1/6 123 | p(X=3)=5/6 * 5/6 * 1/6 124 | ...... 125 | p(X=n)=(1-1/6)^(n-1) * 1/6 126 | ``` 127 | 128 | 那么期望值就是: 129 | $$ 130 | E(X)=\sum^{n}_{j=1} j \cdot {(1-p)}^{(n-1)} \cdot p 131 | $$ 132 | 当n趋近于无穷大时,上面的公式可以采用微积分的知识(我忘了)推导为: 133 | $$ 134 | E(X)=\frac{1}{p} 135 | $$ 136 | 137 | #### 独立随机变量 138 | 139 | $$ 140 | 随机变量X和Y在样本空间S上是独立的,则 \\ 141 | p(X=r_1 \cap Y=r_2)=p(X=r_1) \cdot p(Y=r_2) 142 | $$ 143 | 144 | 这个很简单,抛开随机变量的定义,就是两个相互独立的事情,其一起发生的概率是各自发生概率的乘积。 145 | 146 | 在上面的基础上,再加上期望值的概念: 147 | $$ 148 | 随机变量X和Y在样本空间S上是独立的,则 \\ 149 | E(XY)=E(X)\cdot E(Y) 150 | $$ 151 | 这里书上的证明我感觉是有问题的,也可能是我脑子糊涂了,暂时先记下来,需要的时候再用吧。 152 | 153 | ## 方差 154 | 155 | $$ 156 | 方差使用 V(X),或者 \sigma(X) 表示:\\ 157 | V(X)=\sum_{s \in S} (X(s)-E(X))^2 \cdot p(s) 158 | $$ 159 | 160 | 在下面说明方差的真实意义之前,先推导一个下面的公式: 161 | $$ 162 | V(X)=E(X^2)-E(X)^2 163 | $$ 164 | 证明: 165 | $$ 166 | V(X)=\sum_{s \in S} (X(s)-E(X))^2 \cdot p(s)\\ 167 | =\sum_{s \in S} (X(s)^2 - 2X(s)E(X)+E(X)^2) \cdot p(s)\\ 168 | =\sum_{s \in S} X(s)^2 \cdot p(s)-\sum_{s \in S} 2X(s)E(X)p(s)+\sum_{s \in S} E(X)^2p(s)\\ 169 | =E(X^2)-2E(X) \sum_{s \in S} X(s)p(s)+E(X)^2\\ 170 | =E(X^2)-2E(X)E(X)+E(X)^2 171 | =E(X^2)-E(X) 172 | $$ 173 | 其中一些点的说明: 174 | $$ 175 | E(X)是固定值,所以可以单独抽离出来。\\ 176 | 并且 \sum_{s \in S}p(s)=1。\\ 177 | $$ 178 | 再来证明下面的值: 179 | $$ 180 | 如果 E(X)=\mu,则 V(X)=E((X-\mu)^2) 181 | $$ 182 | 183 | 证明: 184 | $$ 185 | E((X-\mu)^2)=E(X^2-2X \mu+{\mu}^{2})\\ 186 | =E(X^2)-E(2X\mu)+E({\mu}^{2})\\ 187 | =E(X^2)-2\mu E(X)+{\mu}^{2}\\ 188 | =E(X^2)-2\mu \cdot \mu+ \mu \cdot \mu\\ 189 | =E(X^2)-{\mu}^2\\ 190 | =E(X^2)-(E(X))^2 191 | =V(X) 192 | $$ 193 | 194 | #### 比安梅公式 195 | 196 | $$ 197 | 对于在样本空间中互相独立的随机变量 X_1,X_2,X_3 \cdots X_n,\\ 198 | V(X_1+X_2+X_3 \cdots X_n)=V(X_1)+V(X_2)+V(X_3) \cdots V(X_n) 199 | $$ 200 | 201 | 证明: 202 | $$ 203 | V(X+Y)=E((X+Y)^2)-(E(X+Y))^2=E(X^2+2XY+Y^2)-(E(X)+E(Y))^2\\ 204 | =E(X^2)+2E(XY)+E(Y^2)-(E(X))^2-2E(X)E(Y)-(E(Y))^2\\ 205 | =E(X^2)+2E(X)E(Y)+E(Y^2)-(E(X))^2-2E(X)E(Y)-(E(Y))^2\\ 206 | =E(X^2)-(E(X))^2+E(Y^2)-(E(Y))^2\\ 207 | =V(X)+V(Y) 208 | $$ 209 | 更多的参数只需要在上面的基础之上进行证明下去。 210 | 211 | #### 切比雪夫不等式 212 | 213 | $$ 214 | r \in N^+,那么 \\ 215 | p(|X(s)-E(X)|>=r) <= \frac{V(X)}{r^2} 216 | $$ 217 | 218 | 上面的定义啥意思呢?简单来说就是对于样本空间中的值,其值与期望值差的绝对值大于r的概率,小于方差除以r的平方。 219 | 220 | 证明: 221 | $$ 222 | 设事件 A = \{s\in S | |X(s)-E(X)|>=r\}\\ 223 | V(X)=\sum_{s \in S}(X(s)-E(X))^2 \cdot p(s)\\ 224 | =\sum_{s \in A}(X(s)-E(X))^2 \cdot p(s)+\sum_{s \notin A}(X(s)-E(X))^2 \cdot p(s)\\ 225 | 首先看 \sum_{s \in A}(X(s)-E(X))^2 \cdot p(s) 的部分,因为是集合A的元素,所以 (X(s)-E(X))>r,所以 \sum_{s \in A}(X(s)-E(X))^2 \cdot p(s) > \sum_{s \in A} r^2 p(s)。\\ 226 | \sum_{s \notin A}(X(s)-E(X))^2 \cdot p(s) 肯定大于0,所以\\ 227 | V(X)>=\sum_{s \in A} r^2 p(s),即\\ 228 | p(A)<=\frac{V(X)}{r^2} 229 | $$ 230 | -------------------------------------------------------------------------------- /8.1 递推关系的应用.md: -------------------------------------------------------------------------------- 1 | # 8.1 递推关系的应用 2 | 3 | #### 兔子和斐波那契数列 4 | 5 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gmqzteyquhj30bb0cimxo.jpg) 6 | 7 | 简单来说就是一个僵尸,初始等级为1,每过一个月提升1级,升级到2级之后就可以感染下一个人,将其变成1个1级的僵尸。(我不喜欢兔子的那个例子,因为我总是在纠结一个公兔和多个母兔子的问题)。 8 | 9 | 然后用递归来计算上面的问题就是: 10 | 11 | ```php 12 | function getNumber($month){ 13 | if($month==1){ 14 | return [1=>1,2=>0]; 15 | } 16 | $lastMonth=getNumber($month-1); 17 | return [1=>$lastMonth[2],2=>($lastMonth[2]+$lastMonth[1])]; 18 | } 19 | 20 | $result=getNumber(6); 21 | 22 | print_r($result); 23 | /** 24 | Array 25 | ( 26 | [1] => 3 27 | [2] => 5 28 | ) 29 | **/ 30 | ``` 31 | 32 | #### 汉诺塔 33 | 34 | 这个资料很多了,我是参考了[B站的这个视频](https://www.bilibili.com/video/BV1qs411R7i3)。 35 | 36 | 这里仅仅计算完成汉诺塔需要多少步,并不涉及其中的具体步骤: 37 | 38 | ```php 39 | totoalStepsNumber($dishNumber-1); 47 | } 48 | } 49 | 50 | $town=new Town(); 51 | print $town->totoalStepsNumber(4); 52 | ``` 53 | 54 | 这里的思路很简单,就像宋丹丹和赵本山的那个小品一样,把大象关进冰箱需要几步,3步:打开冰箱门,把大象放进冰箱,关上冰箱门。 55 | 56 | 这里是同样的意义,无论中间的具体操作是什么,移动第i个汉诺塔的盘子,都需要先将前面`i-1`个盘子移动到另一个盘子上,然后移动这第i个汉诺塔盘子,然后再将前面第`i-1`个盘子移动到这个盘子上。 57 | 58 | #### 不包含连续两个0的字符串 59 | 60 | 故名思义,就是在长度为n的字符串中,所有不包含连续两个0的字符串总量有多少? 61 | 62 | 这里我看错书上的意思,结果写成了获取所有的可能值的代码,但是结合这个看,可以更好理解总量的部分: 63 | 64 | ```php 65 | 0, 147 | 2=>0, 148 | 3=>1, 149 | 4=>0, 150 | 5=>0, 151 | 6=>2, 152 | 7=>4 153 | ]; 154 | 155 | $sites=[ 156 | 1=>10, 157 | 2=>20, 158 | 3=>20, 159 | 4=>30, 160 | 5=>100, 161 | 6=>20, 162 | 7=>10 163 | ]; 164 | $cache=[]; 165 | 166 | function opt($n){ 167 | global $sites,$p,$cache; 168 | if(isset($cache[$n])){ 169 | return $cache[$n]; 170 | } 171 | if($n<=0){ 172 | return 0; 173 | } 174 | $cache[$n]=max(opt($n-1),opt($p[$n])+$sites[$n]); 175 | return $cache[$n]; 176 | } 177 | 178 | print opt(7); 179 | print PHP_EOL; 180 | print_r($cache); 181 | ``` 182 | 183 | 输出结果: 184 | 185 | ```bash 186 | 100 187 | Array 188 | ( 189 | [1] => 10 190 | [2] => 20 191 | [3] => 30 192 | [4] => 30 193 | [5] => 100 194 | [6] => 100 195 | [7] => 100 196 | ) 197 | ``` 198 | 199 | -------------------------------------------------------------------------------- /8.2 求解线性递推关系.md: -------------------------------------------------------------------------------- 1 | # 8.2 求解线性递推关系 2 | 3 | ### 常系数的k阶线性齐次递推关系 4 | 5 | “ 6 | $$ 7 | 一个常系数的k阶线性齐次递推关系是形如:\\ 8 | a_n=c_1 \cdot {a}_{n-1}+c_2 \cdot {a}_{n-2}+c_3 \cdot {a}_{n-3}+\cdots c_k \cdot {a}_{n-k}\\ 9 | 的递推关系,其中 c_1,c_2,c_3 \cdots c_k 是实数,且 c_k \neq 0 10 | $$ 11 | ” 12 | 13 | 乍一看很迷的一个定义,一个一个拆解其中的定义: 14 | 15 | - 常系数:`c1,c2,c3......ck`都是常数,且在其中没有n的变量之类的 16 | - k阶:`a_n`的值由前面的`k`项来决定 17 | - 线性:`a_n`的值是由前面几项的倍数之和 18 | - 齐次:其中各项都是`a_j`的倍数 19 | 20 | 举几个例子: 21 | $$ 22 | p_n=(1.11){p}_{n-1}:1阶齐次线性递推关系\\ 23 | f_n={f}_{n-1}+{f}_{n-2}:2阶齐次线性递推关系\\ 24 | a_n=a_5:5阶齐次线性递推关系\\ 25 | a_n={a}_{n-1}+{a}_{n-2}^{2}:非线性\\ 26 | H_n=2\cdot {H}_{n-1}+1:非齐次\\ 27 | B_n=n \cdot {B}_{n-1}:非常系数 28 | $$ 29 | 30 | --------------- 31 | 32 | #### 求解常系数线性齐次递推关系 33 | 34 | 简单点来说就是将上面的常系数线性齐次递推关系转换成`n`和`a_n`的函数。 35 | 36 | 首先是第一种形式的递推关系的解: 37 | $$ 38 | 递归关系的形式如下:a_n=c_1 \cdot {a}_{n-1}+c_2 \cdot {a}_{n-2},其中 c_1,c_2 \in R \\ 39 | 再来要求:r^2 - c_1 \cdot r -c_2=0,有两个不相等的解 r_1,r_2。\\ 40 | 那么 a_n= k_1 \cdot {r}_{1}^{n}+k_2 \cdot {r}_{2}^{n}\ 就是上面递推关系的解\\ 41 | k_1,k_2 \in R,一般情况下可以根据已知条件推算出来 42 | $$ 43 | 例子:求解 44 | $$ 45 | a_n= {a}_{n-1} + 2 \cdot {a}_{n-2} 的解,其中 a_0=2,a_1=7 46 | $$ 47 | 解答过程: 48 | $$ 49 | 套用上面的公式可知:c_1=1,c_2=2,所以 \\ 50 | r^2 - c_1 \cdot r -c_2 = r^2-r-2=0 \\ 51 | 解有2个:r_1=2,r_2=-1 \\ 52 | 所以解为:a_n=k_1 \cdot {r}_{1}^{n}+k_2 \cdot {r}_{2}^{n}=k_1 \cdot 2^n +(-1)^n \\ 53 | 因为\\ 54 | a_0=2=k_1 \cdot 2^0 +(-1)^0 \\ 55 | a_1=7=k_1 \cdot 2^1 +(-1)^1 \\ 56 | 所以解出:k_1=3,k_2=-1 \\ 57 | 所以:a_n=3 \cdot 2^n + (-1) \cdot (-1) ^ n=3 \cdot 2^n - (-1)^n 58 | $$ 59 | 看完例子之后,来证明这样做的原理: 60 | $$ 61 | 假设:\\ 62 | r_1^2-c_1 \cdot r_1-c_2=0\\ 63 | r_2^2-c_1 \cdot r_2-c_2=0\\ 64 | r_1 \neq r_2 \\ 65 | a_n=k_1 {r}_{1}^n+k_2 {r}_{2}^{n} \\ 66 | 那么:\\ 67 | a_n=k_1 {r}_{1}^{n-2} \cdot{r}_{1}^{2} +k_2 {r}_{2}^{n-2} \cdot {r}_{2}^{2}\\ 68 | =k_1 {r}_{1}^{n-2}(c_1 \cdot r_1+c_2)+k_2 {r}_{2}^{n-2} (c_1 \cdot r_2+c_2) \\ 69 | =k_1 {r}_{1}^{n-1} c_1+ k_1 {r}_{1}^{n-2} c_2 + k_2 {r}_{2}^{n-1} c_1+k_2 {r}_{2}^{n-2} c_2 \\ 70 | =(k_1 {r}_{1}^{n-1}+k_2 {r}_{2}^{n-1}) \cdot c_1+(k_1 {r}_{1}^{n-2}+k_2 {r}_{2}^{n-2}) \cdot c_2\\ 71 | ={a}_{n-1} \cdot c_1+{a}_{n-2} \cdot c_2\\ 72 | 所以在假设成立的条件下:\\ 73 | a_n=k_1 {r}_{1}^n+k_2 {r}_{2}^{n}是递推关系 a_n={a}_{n-1} \cdot c_1+{a}_{n-2} \cdot c_2的解 74 | $$ 75 | 下面还需要证明一个东西:k1和k2一定存在吗? 76 | $$ 77 | 假设这两个值一定存在,则:\\ 78 | a_0=k_1 \cdot {r}_{1}^{0}+k_2 \cdot {r}_{2}^{0}=k_1+k_2 \\ 79 | a_1=k_1 \cdot {r}_{1}^{1}+k_2 \cdot {r}_{2}^{1}=k_1 \cdot r_1 +k_2 \cdot r_2\\ 80 | 用解二元一次方程组的方式来解,可以得出:\\ 81 | k_1=\frac{a_1-a_0 \cdot r_2}{r_1-r_2}\\ 82 | k_2=a_0-k_1=\frac{a_0 \cdot r_1-a_1}{r_1-r_2}\\ 83 | 因为 r_1 \neq r_2,所以上面的方程一定有解 84 | $$ 85 | 86 | ----------- 87 | 88 | 在上面的证明过程中,我们有一个要求是 89 | $$ 90 | r^2-c_1 \cdot r -c_2 =0 有两个解,如果其只有一个相同的解,那么就是这里考虑的内容了。 91 | $$ 92 | 还是模仿上面的定义: 93 | $$ 94 | 递推关系如下:a_n=c_1 \cdot {a}_{n-1}+c_2 \cdot {a}_{n-2} \\ 95 | 再来要求:r^2-c_1 \cdot r-c_2=0,只有一个解 r_0\\ 96 | 那么:a_n=k_1 {r}_{0}^n+k_2 \cdot n \cdot {r}_{0}^n \\ 97 | 就是递推关系的解 98 | $$ 99 | 这个的证明我推导的时候总是有一个值消不掉,可能是我推导有问题,所以暂时没有证明。 100 | 101 | ------------ 102 | 103 | 在上面只有2阶的情况下,如果是多阶的情况下: 104 | $$ 105 | 如果 r_n 是对于方程:\\ 106 | r^k-c_1 \cdot {r}^{k-1} + c_2 \cdot {r}^{k-2} \cdots + c_k =0 的k个不同的解,则\\ 107 | a_n=k_1 {r}_{1}^{n}+k_2 {r}_{2}^{n}+k_3 {r}_{3}^{n} \cdots k_n {r}_{k}^{n} 是 \\ 108 | a_n=c_1 {a}_{n-1}+ c_2 {a}_{n-2}+ \cdots c_k {a}_{n-k}的递推关系的解 109 | $$ 110 | 111 | 同时,这里的r与k组成的方程叫做**特征方程**,方程的解,也就是`r_n`的值叫做**特征根**。 112 | 113 | 例子: 114 | $$ 115 | 假设 a_0=2,a_1=5,a_2=15,a_n=6 \cdot {a}_{n-1}-11 \cdot {a}_{n-2}+6 \cdot {a}_{n-3} \\ 116 | 求递推关系的解:\\ 117 | 首先 c_1=6,c_2=-11,c_3=6,k=3,所以 \\ 118 | r^3-6 \cdot r^2 +11 \cdot r-6=0\\ 119 | 得出:r_1=1,r_2=2,r_3=3 \\ 120 | 同时因为:\\ 121 | a_0=2=k_1 \cdot 1^0 + k_2 \cdot 2^0 + k_3 \cdot 3^0 \\ 122 | a_1=5=k_1 \cdot 1^1 + k_2 \cdot 2^1 + k_3 \cdot 3^1 \\ 123 | a_2=15=k_1 \cdot 1^2 + k_2 \cdot 2^2 + k_3 \cdot 3^2 \\ 124 | 所以:k_1=1,k_2=-1,k_3=2 \\ 125 | 所以:a_n=1 \cdot 1^n +(-1) \cdot 2^n + 2 \cdot 3^n =1-2^n+2\cdot 3^n 126 | $$ 127 | 128 | ----------- 129 | 130 | 上面是k个不同的解,如果其中有相同的解时: 131 | $$ 132 | 假设特征方程为:\\ 133 | r^k-c_1 \cdot {r}^{k-1} + c_2 \cdot {r}^{k-2} \cdots + c_k =0,\\ 134 | 特征根中的重数(相同的值的个数)分别为 m_1,m_2,m_3 \cdots m_t \\ 135 | 那么对于方程:\\ 136 | a_n=c_1 {a}_{n-1}+ c_2 {a}_{n-2}+ \cdots c_k {a}_{n-k}的解为:\\ 137 | a_n=({k}_{1.0}+{k}_{1,1} \cdot n+ {k}_{1,2} \cdot n^2 + {k}_{1,3} \cdot n^3 \cdots {k}_{1,m_1-1} \cdot {n}^{m_1-1}) {r}_{1}^{n} \\ 138 | +({k}_{2.0}+{k}_{2,1} \cdot n+ {k}_{2,2} \cdot n^2 + {k}_{2,3} \cdot n^3 \cdots {k}_{2,m_2-1} \cdot {n}^{m_2-1}) {r}_{2}^{n} \\ 139 | \vdots \\ 140 | +({k}_{t.0}+{k}_{t,1} \cdot n+ {k}_{t,2} \cdot n^2 + {k}_{t,3} \cdot n^3 \cdots {k}_{t,m_t-1} \cdot {n}^{m_t-1}) {r}_{t}^{n} 141 | $$ 142 | 143 | 例子: 144 | $$ 145 | 已知:a_0=1,a_1=-2,a_2=-1,a_n=-3 \cdot {a}_{n-1}-3 \cdot {a}_{n-2} - {a}_{n-3},求这个递推关系的解。\\ 146 | 解答过程:\\ 147 | k为3,所以特征方程为 r^3+3 \cdot r^2 + 3 \cdot r^2+1=0 \\ 148 | 特征根为 r_0=-1,为重根。\\ 149 | 所以 a_n=({k}_{1,0}+{k}_{1,1}\cdot n+{k}_{1,2} \cdot n^2) \cdot (-1)^n\\ 150 | 同时:\\ 151 | a_0=1=({k}_{1,0}+{k}_{1,1}\cdot 0+{k}_{1,2} \cdot 0^2) \cdot (-1)^0 \\ 152 | a_1=-2=({k}_{1,0}+{k}_{1,1}\cdot 1+{k}_{1,2} \cdot 1^2) \cdot (-1)^1 \\ 153 | a_3=-3=({k}_{1,0}+{k}_{1,1}\cdot 2+{k}_{1,2} \cdot 2^2) \cdot (-1)^2 \\ 154 | 所以:\\ 155 | {k}_{1,0}=1 \\ 156 | {k}_{1,1}=3\\ 157 | {k}_{1,2}=-2 \\ 158 | 所以:a_n=(1+3n-2 \cdot n^2) \cdot (-1)^n 159 | $$ 160 | -------------------------------------------------------------------------------- /8.3 分治算法和递推关系.md: -------------------------------------------------------------------------------- 1 | # 8.3 分治算法和递推关系 2 | 3 | 基础内容: 4 | $$ 5 | 假设 f(n)为求解问题的规模的总步数,g(n)表示每一步中额外的步骤。\\ 6 | 假设递推关系中,每次都将问题拆分为d个更小的问题,那么\\ 7 | f(n)=f(\frac{n}{d})+g(n) 8 | $$ 9 | 例如[归并排序](https://blog.csdn.net/YQXLLWY/article/details/112141283) 10 | 11 | 其总数就可以表示为`f(n)=2f(n/2)+n` 12 | 13 | 在上面的基础之上: 14 | 15 | ### g(n)为固定长度 16 | 17 | “ 18 | $$ 19 | 设f是满足递推关系:\\ 20 | f(n)=af(\frac{n}{b})+c \\ 21 | 的增函数,即g(n)为固定长度,其中 a,c \in R, b \in N,那么 \\ 22 | f(n) 是 23 | \begin{cases} 24 | O({n}^{\log_{b} a}) & a>1 \\ 25 | O(\log_b n) & a=1 26 | \end{cases} 27 | \\ 28 | 如果 n=b^k,a \neq 1,f(n)=C_1 {n}^{\log_b a}+C_2\\ 29 | C_1=f(1)+\frac{c}{a-1},C_2=\frac{-c}{a-1} 30 | $$ 31 | ” 32 | 33 | [大O表示法见这里](https://blog.csdn.net/YQXLLWY/article/details/111416340) 34 | 35 | 先来证明大O表示法所对应的值来源: 36 | $$ 37 | f(n)=af(\frac{n}{b})+g(n)\\ 38 | =a(af(\frac{n}{b^2})+g(\frac{n}{b}))+g(n)\\ 39 | =a^3 f(\frac{n}{b^3})+a^2 g(\frac{n}{b^2})+ag(\frac{n}{b})+g(n)\\ 40 | \vdots \\ 41 | =a^k f(\frac{n}{b^k})+\sum^{k-1}_{j=0}a^j g(\frac{n}{b^j})\\ 42 | 因为 \frac{n}{b^k}=1,所以 \\ 43 | f(n)=a^k f(1)+\sum^{k-1}_{j=0}a^j g(\frac{n}{b^j}) 44 | $$ 45 | 在上面的基础之上,再进行接下来的内容: 46 | $$ 47 | 令 n=b^k,同时假设 g(n)=c。\\ 48 | 于是上面的式子就可以替换成:\\ 49 | f(n)=a^k f(1)+c\sum_{j=0}^{k-1} a^j\\ 50 | 当 a=1时,f(n)=f(1)+ck=f(1)+c \log_b n,所以 O(\log_b n)\\ 51 | 当 a>1时,f(n)=a^k f(1)+c \cdot \frac{a^k-a}{a-1}\\ 52 | =a^k f(1)+ c \frac{a^k}{a-1}-c\frac{a}{a-1} \\ 53 | =a^k (f(1)+c \frac{1}{a-1})-c\frac{a}{a-1} \\ 54 | 令 C_1=f(1)+c \frac{1}{a-1},且 C_1 肯定是实数\\ 55 | 同理令 C_2=c\frac{a}{a-1},且 C_2 \in R,所以 \\ 56 | f(n)=a^k \cdot C_1-C_2,所以 O({n}^{\log_{b} a}) 57 | $$ 58 | [几何序列求和的公式见这里](https://blog.csdn.net/YQXLLWY/article/details/111305452) 59 | 60 | 这里再说明一下上面的`a>1`时,大O值的由来: 61 | $$ 62 | a^k={a}^{\log_b n}={n}^{\log_b a},这里采用的是对数函数的互换性质。 63 | $$ 64 | 附录:对数函数互换性质证明 65 | $$ 66 | 先证明一个性质:k \cdot \log_b M=\log_b M^k。\\ 67 | 证明:令 a=\log_b M^k,所以 b^a={M}^{k},即 b={M}^{\frac{k}{a}},\\ 68 | 所以 \log_{b} M=\frac{k}{a},即 a \log_{b} M=k 69 | $$ 70 | 在上面那条性质的基础之上,再来证明下面这个: 71 | $$ 72 | {M}^{\log_{a} N}={N}^{\log_{a} M},称为互换的形式。\\ 73 | 证明:\\ 令 a^k=N,所以 {N}^{\log_{a} M}={a}^{k \log_{a} M}= M^k={M}^{\log_a N} 74 | $$ 75 | 76 | ### g(n)长度与n有关 77 | 78 | 在上面我们假定了`g(n)`的长度为固定值,下面开始讨论如果`g(n)`的长度与`n`有关。 79 | 80 | “ 81 | $$ 82 | 设f是满足递推关系:\\ 83 | f(n)=a f(\frac{n}{b})+c n^d\\ 84 | 其中 a,b,c,d \in R\\ 85 | f(n)是 86 | \begin{cases} 87 | O(n^d) & ab^d 90 | \end{cases} 91 | $$ 92 | ” 93 | 94 | 这个的证明我能力不足,解不开。 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /8.5 容斥.md: -------------------------------------------------------------------------------- 1 | # 8.5 容斥 2 | 3 | 当只有3个集合时,容斥原理的计算公式就是: 4 | 5 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gn1inxsk7vj30c80ac3z0.jpg) 6 | $$ 7 | A \cup B \cup C=|A|+|B|+|C|-|A \cap B|-|A \cap B|-|B \cap C|+|A \cap B \cap C| 8 | $$ 9 | 这个很容易理解,但是在上面的基础之上进行扩充呢?假设集合的个数为n时,如何表示所有集合的值呢? 10 | $$ 11 | |A_1 \cup A_2 \cup A_3 \cdots A_n|=\sum_{1<=t<=n} |A_t|-\sum_{1<=i 3\\ 35 | P_2=x_2 > 4\\ 36 | P_3=x_3 > 6\\ 37 | N(P_1)=x_1 >3 \equiv x_1 \geq 4=C(9,2)\\ 38 | N(P_2)=C(8,2) \\ 39 | N(P_3)=C(6,2) 40 | $$ 41 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gn3t44ibccj30jx052t8k.jpg) 42 | 43 | 这里解释一下`N(P1)`的情况,为了保证其中一个值一定大于等于4,所以我们就从原先的队列中剔除4个,等到排列结束后,将其加还给x1,这样就可以保证x1一定大于等于4了。 44 | 45 | 比如上面的第二张图,乍一看结果是x1=0,x2=6,x3=1,但是x1还需要加上预分配给它的4个,于是结果就是x1=4,x2=6,x3=1。 46 | 47 | 其他的P2,P3也是一样的思路。 48 | 49 | 接下来就是 50 | $$ 51 | N(P_1P_2)=C(4,2)\\ 52 | N(P_1P_3)=1,这个很容易理解,如果x_1>3,x_3>6,那么只有1种组合,x_1=4,x_2=0,x_3=7\\ 53 | N(P_2P_3)=0,这个同理,这种情况下根本没有解 54 | $$ 55 | 下面说一下N(P1P2)的值的来源: 56 | 57 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gn3tobr7l9j30jk04ymx0.jpg) 58 | 59 | 首先,因为确定x1,x2都大于0,所以开头的那两个白格子消失。 60 | 61 | 接下来就是去除掉预留个x1和x2的总共7个格子。所以按照第二张图中所展示的,x1=1,x2=3,x3=0,加上预留值之后:x1=4,x2=7,x3=0。 62 | 63 | 最后就是一个最容易理解的 64 | $$ 65 | N(P_1P_2P_3)=0 66 | $$ 67 | 因为不可能存在这样的组合。 68 | 69 | 在求的上面的值之后,下面才是开始求我们一开始提出的问题: 70 | $$ 71 | N(P_1 \prime P_2 \prime P_3 \prime)=N-N(P_1)-N(P_2)-N(P_3)+N(P_1P_2)+N(P_1P_3)+N(P_2P_3)-N(P_1P_2P_3)=6 72 | $$ 73 | 74 | ### 埃拉托斯特尼筛法原理 75 | 76 | [埃拉托斯特尼筛法 详细内容见这里](https://blog.csdn.net/YQXLLWY/article/details/111502648) 77 | 78 | 没讲容斥原理之前,这个内容很容易理解,现在就是用容斥的原理说明一下。 79 | $$ 80 | 设N是不超过100的数的总数:N=99\\ 81 | 下面需要求不超过100的素数,根据上面超链接中的定理可知,所有数都可以写作一个或者多个素数的乘积。\\ 82 | 所以令\\ 83 | P_1=(n \mod 2 =0)\\ 84 | P_2=(n \mod 3 =0)\\ 85 | P_3=(n \mod 5 =0)\\ 86 | P_4=(n \mod 7 =0)\\ 87 | 所以\\ 88 | N(P_1 \prime P_2 \prime P_3 \prime P_4 \prime)=N-N(P_1)-N(P_2)-N(P_3)-N(P_4)+N(P_1P_2)+N(P_1P_3)+N(P_2P_3)-N(P_1P_2P_3)+4 89 | $$ 90 | 最后加4是因为2,3,4,7这4个数本身也是素数,在上面的计算中会被忽略掉。 91 | 92 | #### 映上函数个数 93 | 94 | [映上函数定义:简单来说就是集合B中的每个元素都有一个对应的集合A的元素](https://blog.csdn.net/YQXLLWY/article/details/111305452) 95 | 96 | 想要理解这玩意,需要在完全理解映上函数的基础之上。 97 | 98 | **这个我感觉书上的例子有问题,所以下面的计算方式和书上不一样** 99 | 100 | 例子:6元素集合到3元素集合,有多少映上函数? 101 | $$ 102 | N=3^6,这个总数代表一定有\\ 103 | 令3元素集合为(b_1,b_2,b_3)\\ 104 | P_1=(3集合中b_1元素没有映上函数) \\ 105 | P_2=(3集合中b_2元素没有映上函数) \\ 106 | P_3=(3集合中b_3元素没有映上函数) \\ 107 | N(P_1 \prime P_2 \prime P_3 \prime)=N-N(P_1)-N(P_2)-N(P_3)+N(P_1P_2)+N(P_1P_3)+N(P_2P_3)-N(P_1P_2P_3)\\ 108 | =3^6-2^6-2^6-2^6+1+1+1-0=540 109 | $$ 110 | 这里解释一下上面的值的来源: 111 | $$ 112 | N(P_1) 代表 b_1 没有映射函数,所以6元素集合都对应到剩下的2个元素上,比如下面的图片中展示的。 113 | $$ 114 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gn4xg0909hj308z0eidg0.jpg) 115 | 116 | 这样的情况下,总共能使用的组合数为`2^6`。 117 | $$ 118 | 然后再说明 N(P_1P_2),那么情况只有1种,6元素都对应到b_3上去。\\ 119 | 至于 N(P_1P_2P_3) 则是0,因为我们最开始设置总数 3^6 的时候就是6元素一定要有对应的值。 120 | $$ 121 | 122 | ---------- 123 | 124 | 在上面的基础之上,考虑一个问题,真的需要拆分出`b1,b2,b3`吗?其实`b1,b2,b3`的选择可以使用组合的方式来考虑吧,比如将上面的计算函数写成下面的形式: 125 | $$ 126 | 3^6-C(3,1)N(P_i)+C(3,2)N(P_iP_j)-C(3,3)N(P_iP_jP_k)\\ 127 | N(P_i)代表b_i元素没有映上函数,这样的元素有 C(3,1)种\\ 128 | N(P_iP_j)代表b_i,b_j元素没有映上函数,这样的元素有C(3,2)种 129 | $$ 130 | 上面是3个元素,如果拓展一下,m元素集合到n元素集合时,`m>=n`,映上函数的数量为: 131 | $$ 132 | n^m-C(n,1)(n-1)^m+C(n,2)(n-2)^m- \cdots +(-1)^n C(n,n-1)\cdot 1^m 133 | $$ 134 | -------------------------------------------------------------------------------- /9.1 关系及其性质.md: -------------------------------------------------------------------------------- 1 | # 9.1 关系及其性质 2 | 3 | ## 关系的定义 4 | 5 | > 设A和B是集合,一个从A到B的二元关系是AXB的子集。 6 | 7 | 啥意思呢?就是数据库中的外键的意思,比如下面: 8 | 9 | ![image-20210131140545175](https://tva1.sinaimg.cn/large/008eGmZEgy1gn6uepz99nj30de07baa4.jpg) 10 | 11 | 解释一下,就是课程a,有学生1和2选择了,课程b有学生1和3选择了。可以采用下面的形式表示: 12 | 13 | | R | a | b | 14 | | ---- | ---- | ---- | 15 | | 1 | X | X | 16 | | 2 | X | | 17 | | 3 | | X | 18 | 19 | 然后上面的关系可以采用 20 | $$ 21 | (a,1) \in R表示来自集合1的a和来自集合2的1有关系,也可以表示成 a R 1,称为 a与b有关系R。\\ 22 | 如果没有关系可以采用在R上加一个斜线来表示。比如: 23 | $$ 24 | ![image-20210131141058621](https://tva1.sinaimg.cn/large/008eGmZEgy1gn6uk5ygzoj304802eglf.jpg) 25 | 26 | 但是这种符号markdown的latex打不出来,所以接下来我不怎么会常用,会用a与1没有关系R来表示。 27 | 28 | 上面都是考虑两个集合,也可以只考虑一个集合的,即该集合与自身的关系: 29 | 30 | > 集合A上的关系是从A到A的关系。 31 | 32 | ## 关系的性质 33 | 34 | 下面的性质都是考虑集合A上的关系。统一定义集合A为:`{1,2,3,4}` 35 | 36 | #### 自反 37 | 38 | $$ 39 | \forall a \in A((a,a) \in R),则定义在集合A上的关系R称为自反的。 40 | $$ 41 | 42 | [量词的定义见这里](https://blog.csdn.net/YQXLLWY/article/details/111086941) 43 | 44 | - 关系`R1={(1,2),(2,1),(1,1)}`不是自反的,因为没有`(2,2),(3,3),(4,4)` 45 | - 关系`R2={(1,2),(2,1),(1,1),(2,2),(3,3),(4,4)}`是自反的,因为关系中包含了`(1,1),(2,2),(3,3),(4,4)` 46 | 47 | #### 对称 48 | 49 | $$ 50 | \forall a \forall b \in A (aRb\rightarrow bRa) 51 | $$ 52 | 53 | 就是对于任意集合中的元素a,b,只要a和b有关系R,则b和a也有关系R。 54 | 55 | 比如下图: 56 | 57 | ![image-20210131150729056](https://tva1.sinaimg.cn/large/008eGmZEgy1gn6w6y2ghoj309008st8p.jpg) 58 | 59 | 上面图中有颜色的表示有关系。行代表关系中的第一个元素,列代表关系中的第二个元素。 60 | 61 | 只考虑绿色区域,就是对称的关系:`(1,1),(2,2),(3,3),(4,4),(1,2),(2,1),(3,2),(2,3),(4,2),(2,4)` 62 | 63 | 但是加上绿色区域加上红色区域,就不是对称关系了,因为只有`(3,1)`,没有`(1,3)`。 64 | 65 | 或者仅考虑上面逻辑唯一为假的情况: 66 | $$ 67 | aRb为真,bRa为假,时,上面的命题为假。即(a,b) \in R,但是(b,a) \notin R。 68 | $$ 69 | 避免这一情况,上面的命题即为真。 70 | 71 | #### 非对称 72 | 73 | $$ 74 | \forall a \forall b \in R(aRb \rightarrow \neg bRa) 75 | $$ 76 | 77 | 同样考虑上面唯一为假的情况: 78 | $$ 79 | aRb为真,bRa也为真,即(a,b) \in R,(b,a) \in R 80 | $$ 81 | 避免上述情况,即为非对称。 82 | 83 | ![image-20210131145758583](https://tva1.sinaimg.cn/large/008eGmZEgy1gn6vx1porxj309108ot8p.jpg) 84 | 85 | 在上面的图中,还是仅看绿色,就是非对称的,但是红色就不是非对称的,因为`(3,1),(1,3),(2,2)`都是关系R中。 86 | 87 | #### 反对称 88 | 89 | $$ 90 | \forall a \forall b \in R(aRb \and bRa \rightarrow a=b) 91 | $$ 92 | 93 | 老思路,考虑上面的命题唯一为假的情况: 94 | $$ 95 | (a,b) \in R,(b,a) \in R,但是a \neq b 96 | $$ 97 | 避免上述情况,即为反对称。 98 | 99 | ![image-20210131150516646](https://tva1.sinaimg.cn/large/008eGmZEgy1gn6w4o4jowj308o08it8p.jpg) 100 | 101 | 在上面的图中,还是仅看绿色,就是反对称的,但是红色就不是反对称的。 102 | 103 | --------- 104 | 105 | #### 传递 106 | 107 | $$ 108 | \forall a \forall b \forall c \in A((a,b) \in R \and (b,a) \in R \rightarrow (a,c) \in R )\\ 109 | 那么定义在集合A上的关系R是传递的。 110 | $$ 111 | 112 | 比如下面的图 113 | 114 | ![image-20210131152727675](https://tva1.sinaimg.cn/large/008eGmZEgy1gn6wrrojnqj308t08xdfu.jpg) 115 | 116 | 只考虑绿色部分:`(1,2),(2,3),(1,3)`,这就是传递性,但是加上红色部分就没有传递性了,因为`(4,1),(1,3)` ,但是`(4,3)`没有在关系R中。 117 | 118 | #### 关系的组合 119 | 120 | $$ 121 | 设R是集合A到集合B的关系,S是集合B到集合C的关系,R和S的合成是由有序对(a,c)的集合构成的元素,其中\\ 122 | a \in A,c \in C,并且存在一个b \in B,使得 (a,b) \in R \and (b,c)\in S。\\ 123 | 使用 R \circ S代表R与S的合成。 124 | $$ 125 | 126 | 127 | 128 | 比如下面的关系: 129 | 130 | ![image-20210131161411580](https://tva1.sinaimg.cn/large/008eGmZEgy1gn6y4edgtgj30dw0fp3z6.jpg) 131 | $$ 132 | R \circ S=\{(1,0),(1,1),(2,1),(2,2),(3,0)\} 133 | $$ 134 | 135 | $$ 136 | 设R是集合A上的关系。R的n次幂R^n递归的定义为:\\ 137 | R^1=R,{R}^{n+1}={R}^{n} \circ R 138 | $$ 139 | 140 | 在上面的基础上: 141 | $$ 142 | 如果集合A上的R是传递的,当且仅当对 n=1,2,3 \cdots n,有 R^n \subseteq R 143 | $$ 144 | 这个简单来说就是如果集合A上的R是传递的,那么R的n次幂,一直都是R的子集合。 145 | 146 | 证明采用[强归纳法](https://blog.csdn.net/YQXLLWY/article/details/112106627): 147 | $$ 148 | 基础步骤:R^2=R \circ R时,肯定成立,假设 (a,b)\in R,(b,c)\in R,因为在集合A上R是传递的,所以(a,c) \in R\\ 149 | 归纳步骤:假设 R^n 时,命题是成立的。当 {R}^{n+1}时,{R}^{n+1}=R^n \circ R,令 (a,b) \in R^n,(b,c)\in R,因为 R^n \subseteq R,所以 (a,b) \in R \\ 150 | 因为 (a,b) \in R,(b,c) \in R,在集合A上关系R是传递的,所以 (a,c) \in R,所以 {R}^{n+1} \subseteq R 151 | $$ 152 | 153 | -------------------------------------------------------------------------------- /9.3 关系的表示.md: -------------------------------------------------------------------------------- 1 | # 9.3 关系的表示 2 | 3 | 这一章统一都是二元关系。 4 | 5 | ## 矩阵表示 6 | 7 | 这个很简单,就是假设在集合A`(1,2,3)`和集合B`(a,b,c)`上的R为`{(1,a),(2,b),(3,c)}`,则采用矩阵表示为: 8 | $$ 9 | \left[ 10 | \begin{matrix} 11 | 1 & 0 & 0\\ 12 | 0 & 1 & 0\\ 13 | 0 & 0 & 1 14 | \end{matrix} 15 | \right] 16 | $$ 17 | 18 | ## 用图表示 19 | 20 | ![image-20210131170030245](https://tva1.sinaimg.cn/large/008eGmZEgy1gn6zgj2saaj306h09jt8p.jpg) 21 | 22 | 这里列举一下集合A的关系:`(2,1),(3,2),(1,3),(3,3)` 23 | 24 | -------------------------------------------------------------------------------- /9.4 关系的闭包.md: -------------------------------------------------------------------------------- 1 | # 9.4 关系的闭包 2 | 3 | 先扩充两个概念:逆关系和补关系。 4 | $$ 5 | 假设从集合A到集合B的关系为R,即(a,b) \in R \\ 6 | 逆关系:{R}^{-1}:如果 (a,b) \in R,则(b,a) \in R \\ 7 | 补关系:\overline{R}:(a,b) \notin R 8 | $$ 9 | 再来是一个特殊关系的定义——对角关系: 10 | $$ 11 | 对于集合A而言,\Delta 表示对交关系,即 \Delta =\{(a,a)|a \in A\} 12 | $$ 13 | 14 | ## 闭包 15 | 16 | 就是[关系的性质:自反,对称,反对称](https://blog.csdn.net/YQXLLWY/article/details/113480886),如果集合中关系不满足某一性质时,我们通过将一些不缺失的形式关系补上,就能使新的关系满足该性质,满足该性质的关系就叫做**闭包**。根据满足的性质,又叫做自反闭包,对称闭包,反对称闭包。 17 | 18 | 比如: 19 | $$ 20 | 对于集合A=(1,2,3)中的关系:R=\{(1,2),(2,3)\}的传递闭包是什么?\\ 21 | 答:R \cup \{(1,3)\} 22 | $$ 23 | 24 | 25 | 再比如: 26 | $$ 27 | 假设集合A为整数集,关系为 \\ 28 | R=\{(a,b)|ab \},\\ 36 | 求该关系的对称闭包:\\ 37 | 答:R \cup {R}^{-1} 38 | $$ 39 | 40 | ## 有向图中的路径 41 | 42 | 先介绍**图**中常见的几个概念:路径,边,回路/圈。 43 | 44 | ![image-20210131202001402](https://tva1.sinaimg.cn/large/008eGmZEgy1gn7585441oj30dc06ndfx.jpg) 45 | 46 | 在上面的图片中,边有:`(a,b),(b,c),(b,e),(c,d),(d,a),(d,b)` 47 | 48 | 还有由边组成的路径:长度为1的路径`a,b`,长度为2的路径`a,b,c`,长度为3的路径`a,b,c,d`。 49 | 50 | 同时还有长度为4的回路,或者也可以叫做圈:`a,b,c,d,a`。 51 | 52 | 然后将上面的概念套用到集合和关系中。 53 | $$ 54 | 设R是集合A上的关系。从a到b存在一条长为n的路径,当且仅当(a,b) \in R 55 | $$ 56 | 这个就是将上面图中的有向图中的路径对应到关系中。再来就是传递性。 57 | $$ 58 | 设R是集合A上的关系。连通性关系R^*由形如(a,b)的有序对构成,使得在关系R中,\\ 59 | 从顶点a到b之间存在一条长度至少为1的路径。\\ 60 | 说人话就是:\\ 61 | \forall a \forall b \forall c \in A ((a,b) \in R \cap (b,c) \in R \rightarrow (a,c)\in R) 62 | $$ 63 | 然后上面的定义就是传递性的定义嘛,所以: 64 | $$ 65 | 关系R的传递闭包等于连通性关系 R^* 66 | $$ 67 | [关系的幂的概念见这里](https://blog.csdn.net/YQXLLWY/article/details/113480886) 68 | 69 | ### 传递闭包与关系的幂 70 | 71 | $$ 72 | 设M_R是定义在n个元素集合上的关系R的0-1矩阵。那么传递闭包R^*的0-1矩阵是\\ 73 | {M}_{R^*}=M_R \vee {(M_R)}^{[2]} \vee {(M_R)}^{[3]} \cdots {(M_R)}^{[n]} 74 | $$ 75 | 76 | 上面求矩阵的[布尔幂的方法见这里](https://blog.csdn.net/YQXLLWY/article/details/111305452)。这个公式的证明我不会。 77 | 78 | 例子: 79 | $$ 80 | M_R=\left[ 81 | \begin{matrix} 82 | 1 & 0 & 1\\ 83 | 0 & 1 & 0\\ 84 | 1 & 1 & 0 85 | \end{matrix} 86 | \right]\\ 87 | 同时计算\\ 88 | {(M_R)}^{[2]}=\left[ 89 | \begin{matrix} 90 | 1 & 1 & 1\\ 91 | 0 & 1 & 0\\ 92 | 1 & 1 & 1 93 | \end{matrix} 94 | \right] 95 | \\ 96 | {(M_R)}^{[3]}=\left[ 97 | \begin{matrix} 98 | 1 & 1 & 1\\ 99 | 0 & 1 & 0\\ 100 | 1 & 1 & 1 101 | \end{matrix} 102 | \right] 103 | \\ 104 | 根据公式\\ 105 | {M}_{R^*}=M_R \vee {(M_R)}^{[1]} \vee {(M_R)}^{[2]} \vee {(M_R)}^{[3]}=\left[ 106 | \begin{matrix} 107 | 1 & 1 & 1\\ 108 | 0 & 1 & 0\\ 109 | 1 & 1 & 1 110 | \end{matrix} 111 | \right] 112 | $$ 113 | [如果不想手动算,这里有php的代码](https://blog.csdn.net/YQXLLWY/article/details/113486416) 114 | 115 | 这里检查一下,上面的计算结果是否是传递闭包。 116 | $$ 117 | {M}_{R^*}=\{(1,1),(2,1),(3,1),(2,2),(1,3),(2,3),(3,3)\} 118 | $$ 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /9.5 等价关系.md: -------------------------------------------------------------------------------- 1 | # 9.5 等价关系 2 | 3 | ### 等价关系 4 | 5 | 定义: 6 | 7 | > 定义在集合A上的关系如果是自反,对称和传递的,则该关系称为等价关系。 8 | 9 | [自反,对称和传递的定义见这里](https://blog.csdn.net/YQXLLWY/article/details/113480886) 10 | 11 | ### 元素等价 12 | 13 | > 如果集合A中两个关系是被等价关系关联的,则称它们是等价的,记做 a ~ b 14 | 15 | ### 等价类 16 | 17 | $$ 18 | 在一个集合A中,所有a的等价元素组成的子集合叫做a的等价类,记做 \left[ a\right]_R,有时候也可以把\\ 19 | 下标R去掉,写作[a] 20 | $$ 21 | 22 | 例如,对于正整数集合,R为`a=-b或者a=b`。7的等价类就是`[7]={7,-7}` 23 | 24 | ------------- 25 | 26 | ### 等价关系划分集合 27 | 28 | $$ 29 | 假设集合A中的关系R是等价的,a和b具有以下形式:\\ 30 | \begin{array}{ll} 31 | 1 & a R b\\ 32 | 2 & [a]=[b]\\ 33 | 3 & [a] \cap [b] \neq \emptyset 34 | \end{array}\\ 35 | 中的任何一个时,都可以证明另外两个。 36 | $$ 37 | 38 | 这个证明我自己想的,没有抄书上。 39 | $$ 40 | 假设 a,b \in A,且 (a,b) \in R,因为R是等价关系,所以(b,a) \in R,同理,(a,a) \in R,(b,b)\in R。\\ 41 | 所以 [a]=[b], 42 | [a] \cap [b] \neq \emptyset 43 | $$ 44 | 简单来说就是如果一个集合存在等价关系,则我们可以使用该等价关系来划分集合。同时,如果集合可以划分成几部分,我们也可以找到一个等价关系来使其中的各部分符合该关系。 45 | 46 | -------------------------------------------------------------------------------- /9.6 偏序.md: -------------------------------------------------------------------------------- 1 | # 9.6 偏序 2 | 3 | 参照[关系的等价](https://blog.csdn.net/YQXLLWY/article/details/113704921)有当集合中的一个关系具有自反,反对称和传递时,就称为该关系为偏序。 4 | 5 | 所有集合S中该偏序中元素组成的集合叫做偏序集,记做`(S,R)`。 6 | 7 | 在开始举具体的例子前,可以结合等价来理解,等价类的中的元素和集合中的其他所有元素,加上其自身与其自身的关系其实就是偏序。 8 | 9 | 比如在整数集合上,关系`>=`就是偏序关系。所以我们可以表示为`(S,>=)`。 10 | $$ 11 | 像上面这种关系能举的例子很多,所以我们统一使用 (S,\preccurlyeq)来表示偏序。\\ 12 | \preccurlyeq 表示该关系具有偏序的性质。 13 | $$ 14 | 15 | ### 可比 16 | 17 | $$ 18 | 这个很容易理解,如果集合中的两个元素满足指定的关系,并且该关系是偏序时,就说这两个元素是可比的,\\ 19 | 否则就说这两个元素是不可比的。\\ 20 | a \preccurlyeq b,表示这两个元素是可比的。当然,b \preccurlyeq a 也是一样的含义。 21 | $$ 22 | 23 | ### 全序集 / 线序集 / 链 24 | 25 | 在上面可比的情况下,如果一个集合S中所有元素都是可比的,则称该集合S是全序集,线性集,链。该关系R称为全序或线序。 26 | 27 | 比如在整数集合上,关系`<=`是全序集。 28 | 29 | 但是在整数集合上,关系:整除,则不是全序集,因为一些整数不满足整除的关系。 30 | 31 | ### 良序集 32 | 33 | 这个就是能在全序集中找到一个最小元素。 34 | 35 | 比如在正整数集合上,关系`<=`就是良序集,拥有最小元素0。 36 | 37 | 但是在整数集合上,关系`<=`就不是良序集,因为算上负整数,就没有最小值。 38 | 39 | ### 良序归纳原理 40 | 41 | $$ 42 | 设S是一个良序集,如果对所有 y \in S,对于集合内的其他元素x,满足x \prec y时,P(y)为真,那么对所有 x \in S,P(x)为真。 43 | $$ 44 | 45 | 这个与其说证明,不如说是如何去理解这句话,这个很简单。按照上面说的偏序的概念,集合内的一个元素,除了与其等价的元素和自身之外,与其他元素都是偏序的关系。 46 | 47 | 所以上面这个定义其实就是,如果对于集合中的任意一个元素,命题都成立,那么对于集合中,所有元素这个命题都成立。 48 | 49 | ### 字典顺序 50 | 51 | 这个很简单,先说什么是字典排序,说简单点就是对比第一个元素,如果第一个元素一样,就比较下一个元素。 52 | 53 | 可以结合下面的代码来理解: 54 | 55 | ```php 56 | $data2[$index])?1:2; 71 | } 72 | 73 | $data1=[1,2,3]; 74 | $data2=[1,2,1]; 75 | 76 | print dictionarySort($data1,$data2); 77 | ``` 78 | 79 | -------------------------------------------------------------------------------- /Code/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /Code/.idea/Code.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Code/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Code/.idea/php.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Code/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Code/BFS.php: -------------------------------------------------------------------------------- 1 | nodeValue=$nodeValue; 9 | } 10 | public function setNextNodes(Node $node){ 11 | $this->nextNodes[]=$node; 12 | } 13 | } 14 | 15 | function setMap($map,$end,$node,&$checkedMap=[]){ 16 | foreach($node->nextNodes as $node){ 17 | foreach($map[$node->nodeValue] as $city){ 18 | if(isset($checkedMap[$city])){ 19 | continue; 20 | } 21 | $checkedMap[$city]=1; 22 | $thisNode=new Node($city); 23 | $node->setNextNodes($thisNode); 24 | if($city==$end){ 25 | return true; 26 | } 27 | } 28 | setMap($map,$end,$node,$checkedMap); 29 | } 30 | } 31 | 32 | function BFS($node,$end){ 33 | foreach($node->nextNodes as $nextNode){ 34 | /** 35 | * @var $nextNode Node 36 | */ 37 | if($nextNode->nodeValue==$end){ 38 | return true; 39 | } 40 | } 41 | } 42 | 43 | $map=[ 44 | '上海'=>['南京','深圳'], 45 | '南京'=>['上海','北京','武汉'], 46 | '深圳'=>['上海','广州'], 47 | '武汉'=>['南京','北京','广州'], 48 | '北京'=>['南京','武汉','广州'], 49 | '广州'=>['深圳','武汉','北京'] 50 | ]; 51 | 52 | $startNode=new Node('上海'); 53 | $cache=[]; 54 | setMap($map,'北京',$startNode,$cache); 55 | 56 | -------------------------------------------------------------------------------- /Code/BFS2.php: -------------------------------------------------------------------------------- 1 | ['南京','深圳'], 7 | '南京'=>['上海','北京','武汉'], 8 | '深圳'=>['上海','广州'], 9 | '武汉'=>['南京','北京','广州'], 10 | '北京'=>['南京','武汉','广州'], 11 | '广州'=>['深圳','武汉','北京'] 12 | ]; 13 | 14 | function BFS($map,$finalCity,$nextCities,&$passedCities){ 15 | $nextTurnCity=[]; 16 | /** 17 | * 遍历这一轮需要检验的城市 18 | */ 19 | foreach($nextCities as $thisCity){ 20 | foreach($map[$thisCity] as $nextCity){ 21 | $passedCities[$nextCity]=$thisCity; 22 | if($nextCity==$finalCity){ 23 | showResult($passedCities,$finalCity); 24 | return true; 25 | } 26 | /** 27 | * 防止出现 上海 - 南京,南京 - 上海 这样的死循环 28 | */ 29 | $nextTurnCity[]=$nextCity; 30 | } 31 | } 32 | // 开始递归 33 | BFS($map,$finalCity,$nextTurnCity,$passedCities); 34 | } 35 | 36 | // 展示输出结果 37 | function showResult($map,$startCity,&$checkedCity=[]){ 38 | if(isset($checkedCity[$startCity])){ 39 | return false; 40 | } 41 | print $startCity.DIRECTORY_SEPARATOR; 42 | $checkedCity[$startCity]=1; 43 | showResult($map,$map[$startCity],$checkedCity); 44 | } 45 | 46 | $result=[]; 47 | BFS($map,'广州',['上海'],$result); -------------------------------------------------------------------------------- /Code/Cache/temp.json: -------------------------------------------------------------------------------- 1 | {"test":1,"result":"{\"4\":{\"3\":1},\"3\":{\"2\":1},\"2\":{\"1\":1}}","result2":"{\"2\":{\"1\":1},\"4\":{\"1\":1,\"2\":1},\"5\":{\"1\":1,\"2\":1,\"4\":1},\"12\":{\"1\":1,\"2\":1,\"4\":1,\"5\":1},\"20\":{\"1\":1,\"2\":1,\"4\":1,\"5\":1,\"12\":1}}","result3":"{\"20\":{\"12\":1,\"5\":1,\"4\":1,\"2\":1,\"1\":1},\"12\":{\"5\":1,\"4\":1,\"2\":1,\"1\":1},\"5\":{\"4\":1,\"2\":1,\"1\":1},\"4\":{\"2\":1,\"1\":1},\"2\":{\"1\":1}}"} -------------------------------------------------------------------------------- /Code/DFS.php: -------------------------------------------------------------------------------- 1 | label=$label; 13 | } 14 | } 15 | /** 16 | * $nodes 就是模拟前面讲解时采用的表 17 | * $map 对应的图 18 | * $thisNode 递归时采用的点 19 | * $resultNodeLabel 终点 20 | */ 21 | function DFS(&$nodes,$map,&$thisNode,$resultNodeLabel){ 22 | $nextTurnLabel=''; 23 | $minValue=null; 24 | foreach($map[$thisNode->label] as $nextLabel=>$value){ 25 | $node=$nodes[$nextLabel]; 26 | if($node->isChecked){ 27 | continue; 28 | } 29 | if(is_null($node->value) || ($thisNode->value+$value)<$node->value){ 30 | $node->value=$thisNode->value+$value; 31 | $node->previousNodeLabel=$thisNode->label; 32 | if(is_null($minValue) || $node->value<$minValue){ 33 | $minValue=$node->value; 34 | $nextTurnLabel=$node->label; 35 | } 36 | } 37 | } 38 | $thisNode->isChecked=true; 39 | if($thisNode->label==$resultNodeLabel){ 40 | return true; 41 | } 42 | if($nextTurnLabel){ 43 | DFS($nodes,$map,$nodes[$nextTurnLabel],$resultNodeLabel); 44 | } 45 | } 46 | 47 | function showResult($nodes,$label){ 48 | if(!$label){ 49 | return false; 50 | } 51 | print $label.DIRECTORY_SEPARATOR; 52 | $preNode=$nodes[$label]; 53 | showResult($nodes,$preNode->previousNodeLabel); 54 | } 55 | 56 | $map=[ 57 | 'A'=>['D'=>1,'B'=>6], 58 | 'D'=>['A'=>1,'B'=>2,'E'=>1], 59 | 'B'=>['A'=>6,'D'=>2,'E'=>2,'C'=>5], 60 | 'E'=>['D'=>1,'B'=>2,'C'=>5], 61 | 'C'=>['B'=>5,'E'=>5] 62 | ]; 63 | 64 | $startNode=new Node('A'); 65 | $resultLable='C'; 66 | // 可以试试看不走到最后一步,走到中间过程 67 | // $resultLable='E'; 68 | $nodes=[ 69 | 'A'=>$startNode, 70 | 'B'=>new Node('B'), 71 | 'C'=>new Node('C'), 72 | 'D'=>new Node('D'), 73 | 'E'=>new Node('E') 74 | ]; 75 | 76 | DFS($nodes,$map,$startNode,$resultLable); 77 | 78 | showResult($nodes,$resultLable); 79 | -------------------------------------------------------------------------------- /Code/DFS:n皇后问题.php: -------------------------------------------------------------------------------- 1 | =$mapLength){ 14 | return false; 15 | } 16 | // 获取下一个皇后的下标 17 | $columnIndex=getAvaliableNode($queens,$mapLength,$offset); 18 | // 递归到最后一行时,发现没有结果就停止,防止陷入死循环 19 | if (($rowIndex+1)==$mapLength && is_bool($columnIndex)){ 20 | return false; 21 | } 22 | // 正常获取到皇后的位置,则继续下一次递归 23 | if (!is_bool($columnIndex)){ 24 | $queens[$rowIndex]=$columnIndex; 25 | setQueen($queens,$mapLength,$rowIndex+1); 26 | }else{ 27 | // 没有获取到正确的皇后位置,回溯 & 重新开始获取值 28 | array_pop($queens); 29 | setQueen($queens,$mapLength,$rowIndex-1,$offset+1); 30 | } 31 | } 32 | 33 | /** 34 | * 计算下一个可以使用的空格下标 35 | * @param $queens array 已设定的点 36 | * @param $mapLength int n的值 37 | * @param int $offset 回溯时,跳过之前采用的点 38 | * @return false|int 39 | */ 40 | function getAvaliableNode($queens,$mapLength,$offset=0){ 41 | $nextRow=count($queens); 42 | $unavaliableColumnNumber=[]; 43 | foreach ($queens as $rowNumber=>$columnNumber){ 44 | // 计算该列不能使用 45 | $unavaliableColumnNumber[$columnNumber]=1; 46 | // 对角线不能使用 47 | $unavaliableColumnNumber[$columnNumber+($nextRow-$rowNumber)]=1; 48 | $unavaliableColumnNumber[$columnNumber-($nextRow-$rowNumber)]=1; 49 | } 50 | for ($i=0;$i<$mapLength;$i++){ 51 | if (!isset($unavaliableColumnNumber[$i])){ 52 | $offset--; 53 | if ($offset<0){ 54 | return $i; 55 | } 56 | } 57 | } 58 | return false; 59 | } 60 | 61 | $queens=[]; 62 | setQueen($queens,5); 63 | print_r($queens); -------------------------------------------------------------------------------- /Code/FileCache.php: -------------------------------------------------------------------------------- 1 | fileCachePath=__DIR__.DIRECTORY_SEPARATOR."Cache".DIRECTORY_SEPARATOR."temp.json"; 8 | } 9 | /** 10 | * 11 | */ 12 | public static function instance(){ 13 | static $instance; 14 | if(!$instance){ 15 | $instance=new self(); 16 | } 17 | return $instance; 18 | } 19 | 20 | public function set($key,$value){ 21 | $content=file_get_contents($this->fileCachePath); 22 | $content=json_decode($content,1); 23 | $content[$key]=$value; 24 | file_put_contents($this->fileCachePath,json_encode($content)); 25 | } 26 | 27 | public function get($key,$defaultValue=''){ 28 | $content=file_get_contents($this->fileCachePath); 29 | $content=json_decode($content,1); 30 | return isset($content[$key])?$content[$key]:$defaultValue; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Code/debug.php: -------------------------------------------------------------------------------- 1 | $count){ 12 | $result[$word]=round($count/$length,2); 13 | } 14 | $temp=0; 15 | foreach ($result as $word=>$show){ 16 | $temp+=$show; 17 | } 18 | print $temp.PHP_EOL; 19 | return $result; 20 | } 21 | 22 | $string='To be,or not to be:that is the question'; 23 | $result=debug($string); 24 | //print_r($result); -------------------------------------------------------------------------------- /Code/debug2.php: -------------------------------------------------------------------------------- 1 | 0, 5 | 1=>1, 6 | 2=>2, 7 | 3=>3 8 | ]; 9 | // 这个数组就是错位排列 10 | $array2=[ 11 | 0=>1, 12 | 1=>2, 13 | 2=>3, 14 | 3=>0 15 | ]; 16 | // 这个数组不是错位排列,0还在它之前的位置上 17 | $array3=[ 18 | 0=>0, 19 | 1=>2, 20 | 2=>3, 21 | 3=>1 22 | ]; -------------------------------------------------------------------------------- /Code/result.log: -------------------------------------------------------------------------------- 1 | Array 2 | ( 3 | [0] => Array 4 | ( 5 | ) 6 | 7 | [1] => Array 8 | ( 9 | ) 10 | 11 | [2] => 0 12 | ) 13 | 得到的值为:0/0 14 | Array 15 | ( 16 | [0] => Array 17 | ( 18 | [0] => 0 19 | ) 20 | 21 | [1] => Array 22 | ( 23 | [0] => 1 24 | [1] => 1 25 | [-1] => 1 26 | ) 27 | 28 | [2] => 0 29 | ) 30 | 得到的值为:2/1 31 | Array 32 | ( 33 | [0] => Array 34 | ( 35 | [0] => 0 36 | [1] => 2 37 | ) 38 | 39 | [1] => Array 40 | ( 41 | [0] => 1 42 | [2] => 1 43 | [-2] => 1 44 | [3] => 1 45 | [1] => 1 46 | ) 47 | 48 | [2] => 0 49 | ) 50 | 得到的值为:4/2 51 | Array 52 | ( 53 | [0] => Array 54 | ( 55 | [0] => 0 56 | [1] => 2 57 | [2] => 4 58 | ) 59 | 60 | [1] => Array 61 | ( 62 | [0] => 1 63 | [3] => 1 64 | [-3] => 1 65 | [2] => 1 66 | [4] => 1 67 | [5] => 1 68 | ) 69 | 70 | [2] => 0 71 | ) 72 | 得到的值为:1/3 73 | Array 74 | ( 75 | [0] => Array 76 | ( 77 | [0] => 0 78 | [1] => 2 79 | [2] => 4 80 | [3] => 1 81 | ) 82 | 83 | [1] => Array 84 | ( 85 | [0] => 1 86 | [4] => 1 87 | [-4] => 1 88 | [2] => 1 89 | [5] => 1 90 | [-1] => 1 91 | [6] => 1 92 | [1] => 1 93 | ) 94 | 95 | [2] => 0 96 | ) 97 | 得到的值为:3/4 98 | Array 99 | ( 100 | [0] => 0 101 | [1] => 2 102 | [2] => 4 103 | [3] => 1 104 | [4] => 3 105 | ) 106 | -------------------------------------------------------------------------------- /Code/不联系包含0的数列.php: -------------------------------------------------------------------------------- 1 | value=$value; 16 | } 17 | } 18 | 19 | function createBinarySearchTree($storeData){ 20 | $root=new Leaf($storeData[0]); 21 | unset($storeData[0]); 22 | foreach($storeData as $value){ 23 | compare($root,$value); 24 | } 25 | return $root; 26 | } 27 | 28 | /** 29 | * @param $leaf Leaf 30 | * @param $searchValue 31 | * @param bool $isStoreData 32 | * @return bool 33 | */ 34 | function searchValue($leaf,$searchValue,$isStoreData=true){ 35 | if (!$leaf){ 36 | return false; 37 | } 38 | if ($leaf->value==$searchValue){ 39 | return true; 40 | } 41 | if ($isStoreData){ 42 | compare($leaf,$searchValue); 43 | return true; 44 | } 45 | if ($leaf->value>=$searchValue){ 46 | return searchValue($leaf->leftLeaf,$searchValue,$isStoreData); 47 | }else{ 48 | return searchValue($leaf->rightLeaf,$searchValue,$isStoreData); 49 | } 50 | } 51 | 52 | /** 53 | * @param $leaf Leaf 54 | * @param $value 55 | * @return bool 56 | */ 57 | function compare(&$leaf,$value){ 58 | if($leaf->value>=$value){ 59 | if($leaf->leftLeaf){ 60 | compare($leaf->leftLeaf,$value); 61 | return true; 62 | }else{ 63 | $newLeaf=new Leaf($value); 64 | $leaf->leftLeaf=$newLeaf; 65 | return true; 66 | } 67 | } 68 | if($leaf->rightLeaf){ 69 | compare($leaf->rightLeaf,$value); 70 | return true; 71 | }else{ 72 | $newLeaf=new Leaf($value); 73 | $leaf->rightLeaf=$newLeaf; 74 | return true; 75 | } 76 | } 77 | 78 | /** 79 | * @param $leaf Leaf 80 | * @return bool 81 | */ 82 | function showResult($leaf){ 83 | if (!$leaf){ 84 | return true; 85 | } 86 | print "当前节点值为:".$leaf->value.PHP_EOL; 87 | $leaf->leftLeaf && (print "左子值为:".$leaf->leftLeaf->value.PHP_EOL); 88 | $leaf->rightLeaf && (print "右子值为:".$leaf->rightLeaf->value.PHP_EOL); 89 | showResult($leaf->leftLeaf); 90 | showResult($leaf->rightLeaf); 91 | } 92 | // 开始直接编程 93 | $storeData=[50,30,20,67,80,90,49,32]; 94 | $root=createBinarySearchTree($storeData); 95 | showResult($root); 96 | // 尝试搜索一个存在的值 97 | print "67的".(searchValue($root,67,false)?"值存在":"值不存在"); 98 | print PHP_EOL; 99 | // 尝试搜索一个不存在的值 100 | print "100的".(searchValue($root,100,false)?"值存在":"值不存在"); 101 | print PHP_EOL; 102 | // 再搜索一次 103 | print "100的".(searchValue($root,100)?"值存在":"值不存在"); 104 | print PHP_EOL; 105 | showResult($root); -------------------------------------------------------------------------------- /Code/加权动态分配.php: -------------------------------------------------------------------------------- 1 | 0, 5 | 2=>0, 6 | 3=>1, 7 | 4=>0, 8 | 5=>0, 9 | 6=>2, 10 | 7=>4 11 | ]; 12 | 13 | $sites=[ 14 | 1=>10, 15 | 2=>20, 16 | 3=>20, 17 | 4=>30, 18 | 5=>100, 19 | 6=>20, 20 | 7=>10 21 | ]; 22 | $cache=[]; 23 | 24 | function opt($n){ 25 | global $sites,$p,$cache; 26 | if(isset($cache[$n])){ 27 | return $cache[$n]; 28 | } 29 | if($n<=0){ 30 | return 0; 31 | } 32 | $cache[$n]=max(opt($n-1),opt($p[$n])+$sites[$n]); 33 | return $cache[$n]; 34 | } 35 | 36 | print opt(7); 37 | print PHP_EOL; 38 | print_r($cache); -------------------------------------------------------------------------------- /Code/哈夫曼编码.php: -------------------------------------------------------------------------------- 1 | value=$value; 23 | $this->label=$label; 24 | } 25 | } 26 | 27 | /** 28 | * 将字符串转化成上面的类 29 | * @param $string 30 | * @return Leaf 31 | */ 32 | function prepareLeaves($string){ 33 | $length=strlen($string); 34 | $result=[]; 35 | for ($i=0;$i<$length;$i++){ 36 | $data=$string[$i]; 37 | !isset($result[$data]) && $result[$data]=0; 38 | $result[$data]++; 39 | } 40 | $prepare=false; 41 | $leaf=new Leaf(); 42 | foreach ($result as $word=>$count){ 43 | $value=round($count/$length,2); 44 | if (!$prepare){ 45 | $prepare=true; 46 | $leaf->value=$value; 47 | $leaf->label=$word; 48 | continue; 49 | } 50 | $newLeaf=new Leaf($value,$word); 51 | $leaf=sortLeaf($leaf,$newLeaf); 52 | } 53 | return $leaf; 54 | } 55 | 56 | /** 57 | * 构建哈夫曼树 58 | * @param $leaf Leaf 59 | */ 60 | function createHuffmanTree($leaf){ 61 | if (!$leaf->nextLeaf->nextLeaf){ 62 | $indexLeaf=new Leaf($leaf->value+$leaf->nextLeaf->value); 63 | $indexLeaf->leftLeaf=$leaf; 64 | $indexLeaf->rightLeaf=$leaf->nextLeaf; 65 | return $indexLeaf; 66 | } 67 | $newLeaf=new Leaf($leaf->value+$leaf->nextLeaf->value); 68 | $newLeaf->leftLeaf=$leaf; 69 | $newLeaf->rightLeaf=$leaf->nextLeaf; 70 | // 插入新的顶点并排序,保证最前面的2个一定是值最小的2个顶点 71 | $leaf=sortLeaf($leaf->nextLeaf->nextLeaf,$newLeaf); 72 | // 递归,并且之前用过的2个顶点不再继续使用 73 | return createHuffmanTree($leaf); 74 | } 75 | 76 | /** 77 | * 根据哈夫曼树在其中加上编码值 78 | * @param $leaf Leaf 79 | * @param string $preCode 80 | * @return bool 81 | */ 82 | function getWordCode($leaf,$preCode=''){ 83 | if (!$leaf){ 84 | return false; 85 | } 86 | if ($leaf->leftLeaf){ 87 | $leaf->leftLeaf->code=$preCode."0"; 88 | getWordCode($leaf->leftLeaf,$leaf->leftLeaf->code); 89 | } 90 | if ($leaf->rightLeaf){ 91 | $leaf->rightLeaf->code=$preCode."1"; 92 | getWordCode($leaf->rightLeaf,$leaf->rightLeaf->code); 93 | } 94 | } 95 | 96 | /** 97 | * 读取最终的编码值,保存在 result 数组中 98 | * @param $leaf Leaf 99 | * @param $result array 100 | * @return array 101 | */ 102 | function storeResult($leaf,&$result){ 103 | if (!$leaf){ 104 | return $result; 105 | } 106 | print $leaf->label.DIRECTORY_SEPARATOR.$leaf->value.DIRECTORY_SEPARATOR."LeftLabel:".@$leaf->leftLeaf->label.DIRECTORY_SEPARATOR.@$leaf->leftLeaf->value.DIRECTORY_SEPARATOR."RightLabel:".@$leaf->rightLeaf->label.DIRECTORY_SEPARATOR.@$leaf->rightLeaf->value.PHP_EOL; 107 | if ($leaf->label){ 108 | $result[$leaf->label]=$leaf->code; 109 | } 110 | storeResult($leaf->leftLeaf,$result); 111 | storeResult($leaf->rightLeaf,$result); 112 | } 113 | 114 | /** 115 | * 按照从小到大排序叶子节点 116 | * @param $leaf Leaf 117 | * @param $newLeaf Leaf 118 | * @return Leaf 119 | */ 120 | function sortLeaf($leaf,$newLeaf):Leaf{ 121 | if ($leaf->value>$newLeaf->value){ 122 | $newLeaf->nextLeaf=$leaf; 123 | return $newLeaf; 124 | } 125 | $thisLeaf=$leaf->nextLeaf; 126 | $lastLeaf=$leaf; 127 | if (!$thisLeaf){ 128 | $leaf->nextLeaf=$newLeaf; 129 | return $leaf; 130 | } 131 | while ($thisLeaf->nextLeaf && $thisLeaf->value<$newLeaf->value){ 132 | $lastLeaf=$thisLeaf; 133 | $thisLeaf=$thisLeaf->nextLeaf; 134 | } 135 | $lastLeaf->nextLeaf=$newLeaf; 136 | $newLeaf->nextLeaf=$thisLeaf; 137 | return $leaf; 138 | } 139 | 140 | /** 141 | * 代码调用部分 142 | */ 143 | 144 | $string='To be,or not to be:that is the question'; 145 | $indexLeaf=prepareLeaves($string); 146 | $indexLeaf=createHuffmanTree($indexLeaf); 147 | getWordCode($indexLeaf); 148 | $storeResult=[]; 149 | storeResult($indexLeaf,$storeResult); 150 | print_r($storeResult); 151 | 152 | 153 | -------------------------------------------------------------------------------- /Code/图着色:DFS.php: -------------------------------------------------------------------------------- 1 | label=$label; 8 | } 9 | } 10 | 11 | class Side{ 12 | public $leftNodeLabel; 13 | public $rightNodeLabel; 14 | public function __construct($leftNodeLabel,$rightNodeLabel) 15 | { 16 | $this->leftNodeLabel=$leftNodeLabel; 17 | $this->rightNodeLabel=$rightNodeLabel; 18 | } 19 | } 20 | 21 | function createMap(){ 22 | $map=[]; 23 | $map[]=new Side('a','b'); 24 | $map[]=new Side('b','c'); 25 | $map[]=new Side('c','d'); 26 | $map[]=new Side('a','e'); 27 | $map[]=new Side('b','e'); 28 | $map[]=new Side('b','d'); 29 | $map[]=new Side('e','d'); 30 | return $map; 31 | } 32 | 33 | /** 34 | * @param $map array 35 | * @param $leaf Leaf 36 | * @param $leaveArray array 37 | */ 38 | function DFS($map,$leaf,&$leaveArray){ 39 | foreach ($map as $side){ 40 | /** 41 | * @var $side Side 42 | */ 43 | if ($side->rightNodeLabel==$leaf->label && !isset($leaveArray[$side->leftNodeLabel])){ 44 | $newLeaf=new Leaf($side->leftNodeLabel); 45 | $leaf->nextLeave[]=$newLeaf; 46 | $leaveArray[$side->leftNodeLabel]=1; 47 | DFS($map,$newLeaf,$leaveArray); 48 | } 49 | if ($side->leftNodeLabel==$leaf->label && !isset($leaveArray[$side->rightNodeLabel])){ 50 | $newLeaf=new Leaf($side->rightNodeLabel); 51 | $leaf->nextLeave[]=$newLeaf; 52 | $leaveArray[$side->rightNodeLabel]=1; 53 | DFS($map,$newLeaf,$leaveArray); 54 | } 55 | } 56 | } 57 | 58 | function colorCheck($map,$processedLabel,$checkLabel){ 59 | 60 | } 61 | 62 | /** 63 | * @param $indexLeaf Leaf 64 | * @return bool 65 | */ 66 | function showResult($indexLeaf){ 67 | if (!$indexLeaf){ 68 | return false; 69 | } 70 | print "当前节点为:".$indexLeaf->label."。对应的子节点为:"; 71 | foreach ($indexLeaf->nextLeave as $nextLeaf){ 72 | /** 73 | * @var Leaf $nextLeaf 74 | */ 75 | print $nextLeaf->label.DIRECTORY_SEPARATOR; 76 | } 77 | print PHP_EOL; 78 | foreach ($indexLeaf->nextLeave as $nextLeaf){ 79 | showResult($nextLeaf); 80 | } 81 | } 82 | 83 | -------------------------------------------------------------------------------- /Code/字典排序.php: -------------------------------------------------------------------------------- 1 | $data2[$index])?1:2; 16 | } 17 | 18 | $data1=[1,2,3]; 19 | $data2=[1,2,1]; 20 | 21 | print dictionarySort($data1,$data2); -------------------------------------------------------------------------------- /Code/布尔幂.php: -------------------------------------------------------------------------------- 1 | [1,0,1], 29 | 1=>[0,1,0], 30 | 2=>[1,1,0] 31 | ]; 32 | 33 | print_r(booleanPower($data,3)); 34 | -------------------------------------------------------------------------------- /Code/拓扑排序.php: -------------------------------------------------------------------------------- 1 | $b; 7 | } 8 | 9 | function getBaseMap($map,$index,&$returnData){ 10 | foreach($map as $node){ 11 | if(relationShip($map[$index],$node)){ 12 | !isset($returnData[$map[$index]]) && $returnData[$map[$index]]=[]; 13 | $returnData[$map[$index]][$node]=1; 14 | } 15 | } 16 | if(isset($map[$index+1])){ 17 | getBaseMap($map,$index+1,$returnData); 18 | } 19 | } 20 | 21 | $set=[1,2,4,5,12,20]; 22 | $set=[20,12,5,4,2,1]; 23 | $map=[]; 24 | getBaseMap($set,0,$map); 25 | $hasiMapKey='result3'; 26 | Cache::instance()->set($hasiMapKey,json_encode($map)); 27 | hasaiMap($hasiMapKey,4,3); 28 | 29 | function hasaiMap($mapCacheName,$a,$b){ 30 | $map=Cache::instance()->get($mapCacheName); 31 | $map=json_decode($map,1); 32 | $nextB=''; 33 | if(isset($map[$b])){ 34 | foreach($map[$b] as $c=>$useless){ 35 | !$nextB && $nextB=$c; 36 | unset($map[$a][$c]); 37 | } 38 | } 39 | Cache::instance()->set($mapCacheName,json_encode($map)); 40 | if(isset($map[$nextB])){ 41 | hasaiMap($mapCacheName,$b,$nextB); 42 | } 43 | } 44 | 45 | function compare(){ 46 | 47 | } 48 | -------------------------------------------------------------------------------- /Code/斐波那契数列.php: -------------------------------------------------------------------------------- 1 | 1,2=>0]; 6 | } 7 | $lastMonth=getNumber($month-1); 8 | return [1=>$lastMonth[2],2=>($lastMonth[2]+$lastMonth[1])]; 9 | } 10 | 11 | $result=getNumber(6); 12 | 13 | print_r($result); -------------------------------------------------------------------------------- /Code/普林算法.php: -------------------------------------------------------------------------------- 1 | leftNode=$leftNode; 10 | $this->rightNode=$rightNode; 11 | $this->weight=$weight; 12 | } 13 | } 14 | 15 | function createMap(){ 16 | $map=[]; 17 | $map[]=new Side('a','g',40); 18 | $map[]=new Side('a','f',8); 19 | $map[]=new Side('a','b',45); 20 | $map[]=new Side('f','g',35); 21 | $map[]=new Side('b','g',20); 22 | $map[]=new Side('f','e',27); 23 | $map[]=new Side('b','c',12); 24 | $map[]=new Side('e','g',24); 25 | $map[]=new Side('g','c',60); 26 | $map[]=new Side('e','d',6); 27 | $map[]=new Side('d','c',33); 28 | $map[]=new Side('d','g',2); 29 | return $map; 30 | } 31 | 32 | /** 33 | * 普林算法 34 | * @param $map array 地图 35 | * @param $tree array 保存最终的结果 36 | * @param bool $sort 防止递归的时候需要对之前排序好的地图再排序一次 37 | */ 38 | function Prims($map,&$tree,$sort=true){ 39 | $sort && sortMap($map); 40 | $whiteList=[]; 41 | foreach ($tree as $sideLabel=>$side){ 42 | $side[]=$sideLabel; 43 | $whiteList=array_merge($whiteList,$side); 44 | } 45 | $nextSide=getNextNode($map,$whiteList); 46 | if (!empty($nextSide)){ 47 | !isset($tree[$nextSide[0]]) && $tree[$nextSide[0]]=[]; 48 | $tree[$nextSide[0]][]=$nextSide[1]; 49 | Prims($map,$tree,false); 50 | } 51 | } 52 | 53 | /** 54 | * 克鲁斯卡尔算法 55 | * @param $map array 56 | * @param $tree array 57 | */ 58 | function Kruskal($map,&$tree){ 59 | sortMap($map); 60 | $whiteList=[]; 61 | foreach ($map as $side){ 62 | /** 63 | * @var $side Side 64 | */ 65 | // todo 这里的代码有问题,这样会跳过一些点,比如选择 e-d 和 a-f 之后,会跳过 f-e 66 | if (isset($whiteList[$side->leftNode]) && isset($whiteList[$side->rightNode])){ 67 | continue; 68 | } 69 | $whiteList[$side->leftNode]=1; 70 | $whiteList[$side->rightNode]=1; 71 | !isset($tree[$side->leftNode]) && $tree[$side->leftNode]=[]; 72 | $tree[$side->leftNode][]=$side->rightNode; 73 | } 74 | } 75 | 76 | /** 77 | * 获取下一条边 78 | * @param $map 79 | * @param $whiteList 80 | * @return array 81 | */ 82 | function getNextNode($map,&$whiteList){ 83 | $returnData=[]; 84 | foreach ($map as $side){ 85 | /** 86 | * @var $side Side 87 | */ 88 | if ((in_array($side->leftNode,$whiteList) && !in_array($side->rightNode,$whiteList))){ 89 | $returnData=[$side->leftNode,$side->rightNode]; 90 | break; 91 | }elseif (in_array($side->rightNode,$whiteList) && !in_array($side->leftNode,$whiteList)){ 92 | $returnData=[$side->rightNode,$side->leftNode]; 93 | break; 94 | } 95 | } 96 | return $returnData; 97 | } 98 | 99 | /** 100 | * 排序一下,因为这样后续可以直接获取数据 101 | * @param $map 102 | */ 103 | function sortMap(&$map){ 104 | $mapLength=count($map); 105 | for ($outsideIndex=0;$outsideIndex<$mapLength;$outsideIndex++){ 106 | for ($insideIndex=$outsideIndex;$insideIndex<$mapLength;$insideIndex++){ 107 | /** 108 | * @var $outsideSide Side 109 | */ 110 | $outsideSide=$map[$outsideIndex]; 111 | /** 112 | * @var $insideSide Side 113 | */ 114 | $insideSide=$map[$insideIndex]; 115 | if ($outsideSide->weight>$insideSide->weight){ 116 | $map[$outsideIndex]=$insideSide; 117 | $map[$insideIndex]=$outsideSide; 118 | } 119 | } 120 | } 121 | } 122 | 123 | //$tree=['g'=>[]]; 124 | //Prims(createMap(),$tree); 125 | //print_r($tree); 126 | $tree=[]; 127 | Kruskal(createMap(),$tree); 128 | print_r($tree); -------------------------------------------------------------------------------- /Code/树的遍历.php: -------------------------------------------------------------------------------- 1 | label=$label; 10 | } 11 | } 12 | 13 | /** 14 | * 前序遍历 15 | * @param $leaf Leaf 16 | * @param string $result 17 | * @return bool 18 | */ 19 | function VLR($leaf,&$result){ 20 | if (!$leaf){ 21 | return false; 22 | } 23 | $result.=$leaf->label; 24 | VLR($leaf->leftLeaf,$result); 25 | VLR($leaf->rightLeaf,$result); 26 | } 27 | 28 | /** 29 | * 中序遍历 30 | * @param $leaf Leaf 31 | * @param $result string 32 | * @return bool 33 | */ 34 | function LDR($leaf,&$result){ 35 | if (!$leaf){ 36 | return false; 37 | } 38 | if ($leaf->leftLeaf){ 39 | LDR($leaf->leftLeaf,$result); 40 | } 41 | $result.=$leaf->label; 42 | LDR($leaf->rightLeaf,$result); 43 | } 44 | 45 | /** 46 | * 后续遍历 47 | * @param $leaf Leaf 48 | * @param $result string 49 | * @return bool 50 | */ 51 | function LRD($leaf,&$result){ 52 | if (!$leaf){ 53 | return false; 54 | } 55 | LRD($leaf->leftLeaf,$result); 56 | LRD($leaf->rightLeaf,$result); 57 | $result.=$leaf->label; 58 | return false; 59 | } 60 | 61 | // 相关记法部分 62 | 63 | /** 64 | * 解析前缀记法 65 | * @param $string 66 | * @return mixed 67 | */ 68 | function ParseStringVLR($string){ 69 | global $supportOperation; 70 | $stringIndex=strlen($string); 71 | $string=str_split($string); 72 | while ($stringIndex>0){ 73 | $stringIndex--; 74 | if (in_array($string[$stringIndex],$supportOperation)){ 75 | $string[$stringIndex]=calculate($string[$stringIndex],$string[$stringIndex+1],$string[$stringIndex+2]); 76 | unset($string[$stringIndex+1]); 77 | unset($string[$stringIndex+2]); 78 | $string=array_values($string); 79 | $stringIndex=count($string); 80 | } 81 | } 82 | return $string[0]; 83 | } 84 | 85 | /** 86 | * 解析后缀记法 87 | * @param $string 88 | * @return mixed 89 | */ 90 | function ParseStringLRD($string){ 91 | global $supportOperation; 92 | $length=strlen($string)-1; 93 | $string=str_split($string); 94 | $stringIndex=-1; 95 | while ($stringIndex<$length){ 96 | $stringIndex++; 97 | if (in_array($string[$stringIndex],$supportOperation)){ 98 | $string[$stringIndex]=calculate($string[$stringIndex],$string[$stringIndex-2],$string[$stringIndex-1]); 99 | unset($string[$stringIndex-1]); 100 | unset($string[$stringIndex-2]); 101 | $string=array_values($string); 102 | $length=count($string)-1; 103 | $stringIndex=0; 104 | } 105 | } 106 | return $string[0]; 107 | } 108 | 109 | /** 110 | * 解析中缀记法 111 | * @param $string 112 | * @return mixed 113 | */ 114 | function ParseStringLDR($string){ 115 | global $supportOperation; 116 | $length=strlen($string)-1; 117 | $string=str_split($string); 118 | $stringIndex=-1; 119 | while ($stringIndex<$length){ 120 | $stringIndex++; 121 | if (in_array($string[$stringIndex],$supportOperation)){ 122 | $string[$stringIndex]=calculate($string[$stringIndex],$string[$stringIndex-1],$string[$stringIndex+1]); 123 | unset($string[$stringIndex-1]); 124 | unset($string[$stringIndex+1]); 125 | $string=array_values($string); 126 | $length=count($string)-1; 127 | $stringIndex=0; 128 | } 129 | } 130 | return $string[0]; 131 | } 132 | 133 | $supportOperation=['+','-','*','/']; 134 | function calculate($operation,$data1,$data2){ 135 | $result=0; 136 | switch ($operation){ 137 | case "+": 138 | $result=$data1+$data2; 139 | break; 140 | case "-": 141 | $result=$data1-$data2; 142 | break; 143 | case "*": 144 | $result=$data1*$data2; 145 | break; 146 | case "/": 147 | if ($data2!=0){ 148 | $result=round($data1/$data2,2); 149 | } 150 | break; 151 | default: 152 | $result=0; 153 | } 154 | return $result; 155 | } -------------------------------------------------------------------------------- /Code/汉诺塔.php: -------------------------------------------------------------------------------- 1 | totoalStepsNumber($dishNumber-1); 9 | } 10 | } 11 | 12 | $town=new Town(); 13 | print $town->totoalStepsNumber(4); -------------------------------------------------------------------------------- /Code/沃舍尔算法2.php: -------------------------------------------------------------------------------- 1 | $line){ 16 | foreach($line as $columnNumber=>$data){ 17 | if($lineNumber==$n && $data){ 18 | $returnColumnNumber[]=$columnNumber; 19 | } 20 | if($columnNumber==$n && $data){ 21 | $returnLineNumber[]=$lineNumber; 22 | } 23 | } 24 | } 25 | foreach($returnLineNumber as $lineNumber){ 26 | foreach($returnColumnNumber as $columnNumber){ 27 | $map[$lineNumber][$columnNumber]=1; 28 | } 29 | } 30 | } 31 | 32 | $map=[ 33 | 0=>[1,0,1], 34 | 1=>[0,1,0], 35 | 2=>[1,1,0] 36 | ]; 37 | 38 | $newMap=WasherAlgorithm($map); 39 | 40 | print_r($newMap); 41 | -------------------------------------------------------------------------------- /Code/波兰记法.php: -------------------------------------------------------------------------------- 1 | leftLeaf=new Leaf('*'); 8 | $indexLeaf->rightLeaf=new Leaf('+'); 9 | $indexLeaf->leftLeaf->leftLeaf=new Leaf('+'); 10 | $indexLeaf->leftLeaf->leftLeaf->leftLeaf=new Leaf($x); 11 | $indexLeaf->leftLeaf->leftLeaf->rightLeaf=new Leaf($y); 12 | $indexLeaf->leftLeaf->rightLeaf=new Leaf(2); 13 | $indexLeaf->rightLeaf->leftLeaf=new Leaf('-'); 14 | $indexLeaf->rightLeaf->rightLeaf=new Leaf(3); 15 | $indexLeaf->rightLeaf->leftLeaf->leftLeaf=new Leaf($x); 16 | $indexLeaf->rightLeaf->leftLeaf->rightLeaf=new Leaf(4); 17 | return $indexLeaf; 18 | } 19 | 20 | $x=2; 21 | $y=4; 22 | $result=13; 23 | 24 | $indexLeaf=createLeaf($x,$y); 25 | $string=''; 26 | VLR($indexLeaf,$string); 27 | print $string.PHP_EOL; 28 | print ParseStringVLR($string).PHP_EOL; 29 | $string=''; 30 | LRD($indexLeaf,$string); 31 | print $string.PHP_EOL; 32 | print ParseStringLRD($string).PHP_EOL; 33 | $string=''; 34 | LDR($indexLeaf,$string); 35 | print $string.PHP_EOL; 36 | print ParseStringLDR($string); 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Code/深度优先搜索.php: -------------------------------------------------------------------------------- 1 | label=$label; 8 | } 9 | } 10 | 11 | class Side{ 12 | public $leftNodeLabel; 13 | public $rightNodeLabel; 14 | public function __construct($leftNodeLabel,$rightNodeLabel) 15 | { 16 | $this->leftNodeLabel=$leftNodeLabel; 17 | $this->rightNodeLabel=$rightNodeLabel; 18 | } 19 | } 20 | 21 | function createMap(){ 22 | $map=[]; 23 | $map[]=new Side('a','c'); 24 | $map[]=new Side('b','c'); 25 | $map[]=new Side('c','e'); 26 | $map[]=new Side('e','d'); 27 | $map[]=new Side('e','f'); 28 | $map[]=new Side('d','f'); 29 | $map[]=new Side('f','g'); 30 | $map[]=new Side('g','h'); 31 | $map[]=new Side('f','h'); 32 | $map[]=new Side('h','i'); 33 | $map[]=new Side('h','k'); 34 | $map[]=new Side('h','j'); 35 | return $map; 36 | } 37 | 38 | /** 39 | * @param $map array 40 | * @param $leaf Leaf 41 | * @param $leaveArray array 42 | */ 43 | function DFS($map,$leaf,&$leaveArray){ 44 | foreach ($map as $side){ 45 | /** 46 | * @var $side Side 47 | */ 48 | if ($side->rightNodeLabel==$leaf->label && !isset($leaveArray[$side->leftNodeLabel])){ 49 | $newLeaf=new Leaf($side->leftNodeLabel); 50 | $leaf->nextLeave[]=$newLeaf; 51 | $leaveArray[$side->leftNodeLabel]=1; 52 | DFS($map,$newLeaf,$leaveArray); 53 | } 54 | if ($side->leftNodeLabel==$leaf->label && !isset($leaveArray[$side->rightNodeLabel])){ 55 | $newLeaf=new Leaf($side->rightNodeLabel); 56 | $leaf->nextLeave[]=$newLeaf; 57 | $leaveArray[$side->rightNodeLabel]=1; 58 | DFS($map,$newLeaf,$leaveArray); 59 | } 60 | } 61 | } 62 | 63 | /** 64 | * @param $indexLeaf Leaf 65 | * @return bool 66 | */ 67 | function showResult($indexLeaf){ 68 | if (!$indexLeaf){ 69 | return false; 70 | } 71 | print "当前节点为:".$indexLeaf->label."。对应的子节点为:"; 72 | foreach ($indexLeaf->nextLeave as $nextLeaf){ 73 | /** 74 | * @var Leaf $nextLeaf 75 | */ 76 | print $nextLeaf->label.DIRECTORY_SEPARATOR; 77 | } 78 | print PHP_EOL; 79 | foreach ($indexLeaf->nextLeave as $nextLeaf){ 80 | showResult($nextLeaf); 81 | } 82 | } 83 | 84 | //$indexLeaf=new Leaf('f'); 85 | //$map=createMap(); 86 | //$cache=['f'=>1]; 87 | //DFS($map,$indexLeaf,$cache); 88 | //showResult($indexLeaf); 89 | 90 | -------------------------------------------------------------------------------- /Code/点割集.php: -------------------------------------------------------------------------------- 1 | $index){ 13 | $returnData[$line][$index]=$int[$key] ?? 0; 14 | } 15 | } 16 | return $returnData; 17 | } 18 | 19 | function F($map){ 20 | $returnData=[]; 21 | foreach ($map as $setting){ 22 | $result=$setting['A']*$setting['B']*$setting['C']+$setting['A']*neg($setting['B'])*$setting['C']+neg($setting['A'])*$setting['B']*$setting['C']+neg($setting['A'])*$setting['B']*$setting['C']+neg($setting['A'])*neg($setting['B'])*neg($setting['C']); 23 | $result<0 && $result=0; 24 | $result>1 && $result=1; 25 | $returnData[implode(",",$setting)]=$result; 26 | } 27 | return $returnData; 28 | } 29 | 30 | print_r(F(createDefaultArray(3))); 31 | 32 | function neg($return){ 33 | switch ($return){ 34 | case 1: 35 | return 0; 36 | default: 37 | return 1; 38 | } 39 | } 40 | 41 | 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DiscreteMath 2 | 《离散数学及其应用》学习笔记。 3 | 4 | ---------- 5 | 6 | 这里的所有的markdown语法都是我在Mac的Typora上能完美显示的,如果有latex显示不对的地方,可能是软件原因。 7 | 8 | 其中`Code`部分的代码,有的是我没有写完,有的可能是有问题的,我没有时间一一整理了,我的运行环境是php 7.3。 9 | 10 | [我的CSDN博客地址](https://blog.csdn.net/YQXLLWY),这里也有一些备份文件,只是因为latex的支持有问题,所以我特意在这里备份一份数据(因为我知道如果存电脑上,肯定会因为我重装系统把数据弄没掉)。 11 | 12 | 最后祝贺自己,看完了一本黑皮书。 13 | 14 | ---------- 15 | 16 | 在这里主要介绍一下各个章节,以及其关联性。 17 | 18 | ## 第1章:基础:逻辑和证明 19 | 20 | 这一章节很基础,比较麻烦的就是名词一堆。 21 | 22 | 从内容上来说,都是很浅显易懂的部分,如果你按照它的思路去解释那些句子,就会理解起来比较简单一点。 23 | 24 | 从关联性来讲,这一章在后面的比重不是很多,除了用来说明一些定理之外,不会有推导的部分。 25 | 26 | 和12章的布尔代数的概念是类似的。 27 | 28 | ## 第2章:基本结构:集合,函数,序列,求和与矩阵 29 | 30 | 这部分也是内容上比较简单,就是又是一堆名词,但是其中的知识都是很浅显易懂的。 31 | 32 | 从关联性上来说,这一章也算是基础,后面很多地方会用到这里的名词,所以还是不太适合跳过。 33 | 34 | ## 第3章:算法 35 | 36 | 这一章就是一个很单独的模块,时间复杂度和空间复杂度,建议去找其他视频来看。 37 | 38 | 关联性上来说,这一章其实蛮单独的。 39 | 40 | ## 第4章:数论与密码学 41 | 42 | 这一章和其他章节关联性不强,很独立,但是建议从开始一小节一小节的往后看,不要跳过,否则很容易后面看不懂。 43 | 44 | 如果不想看,直接跳过也可以,后面基本没有用到这一块的内容。 45 | 46 | ## 第5章:归纳和递归 47 | 48 | 这一章很简单,弄懂含义就可以了,不需要仔细看。 49 | 50 | 而且后面很多证明都需要这里的内容,所以还是需要了解一下。 51 | 52 | ## 第6章:计数 53 | 54 | 这一章是基础!!!一定要仔细看,否则后面很多章节都会看不懂。 55 | 56 | 至于内容上,老老实实按照按照它的思路走下去,一定要提前理解它试图解决的问题是什么,对应的解决方案是什么,就可以理解其中的内容了。 57 | 58 | ## 第7章:离散概率 59 | 60 | 在第6章的基础之上,加上概率的部分,本质上没有跳出第6章的范畴。 61 | 62 | ## 第8章:高级计数技术 63 | 64 | 和第6章相呼应,简单来说就是考虑的情况更加复杂,如果你第6章没问题,这一章照着它的思路走下去也不会有问题。 65 | 66 | ## 第9章:关系 67 | 68 | 这个有点关系型数据库的设计思路都不会有问题。 69 | 70 | 而且这一章的一些概念在后面图,树部分也有用到,所以需要认真看一下。 71 | 72 | ## 第10章:图 73 | 74 | 超级简单的概念介绍,复杂一点的是后面部分,前几章就是一些基本概念介绍,后面部分考虑的情况复杂一点,不过也不是需要你去解决,看他解决的方式就可以了。 75 | 76 | ## 第11章:树 77 | 78 | 内容安排上和第10章图一样,其中后面部分建议参考其他视频,动态讲解起来可能更加便于理解。 79 | 80 | ## 第12章:布尔代数 81 | 82 | 其中需要注意的就是后面部分的化简电路和设计电路,前面部分就是将第1章的概念用布尔代数的名词解释一遍而已。 83 | 84 | ## 第13章:计算模型 85 | 86 | 天书,看不懂,直接放弃。而且感觉和其他各个章节都是独立的。 87 | 88 | 这里整理一下其中各个部分的关联: 89 | 90 | ```mermaid 91 | graph TD 92 | basic(基础章节) --- p1(第1章) & p2(第2章) & p3(第3章) & p4(第4章) & p5(第5章); 93 | p1 --- p12(第12章); 94 | p2 --- p6(第6章) & p9(第9章); 95 | p6 --- p7(第7章) & p8(第8章); 96 | p9 --- p10(第10章) & p11(第11章); 97 | ``` -------------------------------------------------------------------------------- /哈赛图.md: -------------------------------------------------------------------------------- 1 | # 哈赛图 2 | 3 | 先说啥叫哈赛图,就是简化了一些东西的图,而因为一个叫做哈赛的人很喜欢用这种图,所以叫做哈赛图。 4 | 5 | 哈赛图制作过程。 6 | 7 | 假设集合A为:`{1,2,3,4}`,关系为`a<=b`,所以一般的图为:`(4,4),(4,3),(4,2),(4,2)......` 8 | 9 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gne5nofcapj30b80d13z3.jpg) 10 | 11 | 但是因为关系是自反的,所以我们可以把类似`(4,4),(3,3),(2,2),(1,1)`的线去掉: 12 | 13 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gne5rvmjzxj30b40chmxj.jpg) 14 | 15 | 接下来因为关系是传递的,所以我们把类似`(4,3),(4,2),(4,1),(3,2),(3,1),(2,1)`之类的线去掉: 16 | 17 | ![image-20210206215925950](/Users/yangqingxian/Library/Application%20Support/typora-user-images/image-20210206215925950.png) 18 | 19 | 最后我们再把箭头去掉,得到的就是哈赛图了: 20 | 21 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gne5vq6oqnj30400blq2s.jpg) 22 | 23 | 这个哈赛图很简单,换个复杂一点的哈赛图: 24 | 25 | 集合A=`(1,2,3,4,6,8,12)` 26 | 27 | 关系R:`{(a,b)|b能被a整除}` 28 | 29 | 原本的图: 30 | 31 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gne6bwk117j30fm0dvwfe.jpg) 32 | 33 | 化简后的图: 34 | 35 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gne6cp75myj30ak0a53ym.jpg) 36 | 37 | ## 极大元与极小元 38 | 39 | 这个很简单,极小元就是该偏序集中不大于任何一个其他元素,比如上面的1,极大元则是该偏序集中不存在比该元素大的元素,比如上面的第二个例子中的12和8。 40 | 41 | 比如下面这2个哈赛图: 42 | 43 | 哈赛图1 44 | 45 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gne6mpe0quj30ag05ka9z.jpg) 46 | 47 | 的极小元是a,没有极大元,如果有疑问,那么请问你,b,c,d哪个比较大?如果其中一个比另外两个大的话,那么它们3个元素之间就应该有一条线。 48 | 49 | 哈赛图2 50 | 51 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gne6pqln8zj309r089glm.jpg) 52 | 53 | 这个哈赛图中既没有极大元,也没有极小元。 54 | 55 | ### 上界和下界 56 | 57 | 这个也很好理解,就是在一个偏序集中,如果存在一个元素,假设为a,其小于该偏序集中某些元素组成的子子集A,那么该元素就称为集合A的下界,上界是类似的道理。 58 | 59 | 比如上面的哈赛图1,在`a`就是子集合`(c,e)`的上界。或者哈赛图2中,元素`a`就是子集合`(b,c,d)`的下界。 60 | 61 | 根据上面的定义,我们知道了对于一个偏序集合中的子集合来说,上界和下界的值不一定是固定的,比如下面这个哈赛图: 62 | 63 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gne7lerpdbj309i0gy74j.jpg) 64 | 65 | 对于子集合`(b,d)`来说,f可以作为其上界,g也可以作为其上界,而这些上界中的最小值,叫做**最小上界**,同理,下界也很多,比如h和i,那么其中最大的值,叫做**最大上界**。 66 | 67 | ### 格 68 | 69 | 这个定义就很厉害了: 70 | 71 | “如果一个偏序集中,除了极大元和极小元,任何两个元素都有最小上界和最小下界,就称这个偏序集为格。” 72 | 73 | (这里我修改了书上的定义,书上没有剔除极大元和极小元,但是如果不剔除,那么当定义中的任意两个元素包含极大元或极小元时,格就肯定不存在了) 74 | 75 | 啥意思呢?就是我们知道,一个格子,就是一个菱形,需要有4个点,任意两个元素就是中间的两个点,最小上界,最大下界分别就是菱形上面的点和下面的点。 76 | 77 | 比如下面这个哈赛图: 78 | 79 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gne7x0usk4j30ar0d0mxa.jpg) 80 | 81 | 就是格,我们不考虑极大元和极小元,其中任何两个元素的组合,我们都可以找到最大下界和最小上界。 82 | 83 | 但是对于下面这种哈赛图,就没有格了。 84 | 85 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gne816ke8xj30a10dqaac.jpg) 86 | 87 | 因为元素c和元素d没有最小上界。 88 | 89 | -------------------------------------------------------------------------------- /图的同构.md: -------------------------------------------------------------------------------- 1 | # 图的同构 2 | 3 | 先解释啥叫同构: 4 | 5 | “ 6 | $$ 7 | 设两个图G_1=(V_1,E_1)和G_2(V_2,G_2)。\\ 8 | a,b \in V_1,c,d \in V_2,若存在一个一对一和满射函数:f,\\ 9 | 使得f(a)=c,f(b)=d,并且a和b相邻时,c与d也相邻。 10 | $$ 11 | ” 12 | 13 | 如果那个函数存在,则我们叫`G1`和`G2`同构的,对应的函数叫做同构。 14 | 15 | 比如下面两张图: 16 | 17 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnhcmsen37j30mm0aeq38.jpg) 18 | 19 | 对应的f函数如下所示: 20 | $$ 21 | f(a)=e \\ 22 | f(b)=f \\ 23 | f(d)=g \\ 24 | f(h)=d 25 | $$ 26 | 因为这样的函数存在,所以可以说`G1`和`G2`是同构的。或者换成下面的图片会更好理解: 27 | 28 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gnhcqlrswmj3083093748.jpg) 29 | 30 | 这里只是介绍同构的概念,具体判定同构的算法就没有了。 31 | 32 | -------------------------------------------------------------------------------- /常用LaTex 2.md: -------------------------------------------------------------------------------- 1 | \in 2 | $$ 3 | \in 4 | $$ 5 | \subseteq 6 | $$ 7 | \subseteq 8 | $$ 9 | \emptyset 10 | $$ 11 | \emptyset 12 | $$ 13 | \left\vert 值 \right\vert:基数 14 | $$ 15 | \left\vert 值 \right\vert 16 | $$ 17 | \mathcal{P}(X):幂集 18 | $$ 19 | \mathcal{P}(X) 20 | $$ 21 | \cup:并集 22 | $$ 23 | \cup 24 | $$ 25 | 26 | 27 | \cap:交集 28 | $$ 29 | \cap 30 | $$ 31 | \mid:竖线 32 | $$ 33 | \mid 34 | $$ 35 | \overline{差集} 36 | $$ 37 | \overline{差集} 38 | $$ 39 | \dots 底层位置的三个点 40 | $$ 41 | \dots 42 | $$ 43 | 44 | 45 | \cdots 中间位置的三个点 46 | $$ 47 | \cdots 48 | $$ 49 | \cdot 一个点 50 | $$ 51 | \cdot 52 | $$ 53 | \vdots 54 | $$ 55 | \vdots 56 | $$ 57 | \bullet 一个大点 58 | $$ 59 | \bullet 60 | $$ 61 | \circ 空心的圆点 62 | $$ 63 | \circ 64 | $$ 65 | 66 | 67 | 多列 68 | 69 | ``` 70 | \begin{gathered} 71 | n \\ 72 | \bigcup \\ 73 | i=0 74 | \end{gathered} 75 | {A}_{i} 76 | ``` 77 | 78 | $$ 79 | \begin{gathered} 80 | n \\ 81 | \bigcup \\ 82 | i=0 83 | \end{gathered} 84 | {A}_{i} 85 | $$ 86 | 87 | \sum^{上标}_{小标} 88 | $$ 89 | \sum^{上标}_{下标} 90 | $$ 91 | {\aleph}_{0} 阿里夫零 92 | $$ 93 | {\aleph}_{0} 94 | $$ 95 | 矩阵 96 | 97 | ``` 98 | \begin{vmatrix} 99 | 1&2&3\\ 100 | 4&5&6\\ 101 | 7&8&9 102 | \end{vmatrix} 103 | ``` 104 | 105 | $$ 106 | \begin{vmatrix}1&2&3\\ 4&5&6\\ 7&8&9\end{vmatrix} 107 | $$ 108 | 109 | \delta 克罗内克积 110 | $$ 111 | \delta 112 | $$ 113 | 114 | 下总结 \underbrace{上面的内容}_{下面的内容} 115 | $$ 116 | \underbrace{上面的内容}_{下面的内容} 117 | $$ 118 | 119 | \Omaga:欧米伽 120 | $$ 121 | \Omega 122 | $$ 123 | \Theta:西塔 124 | $$ 125 | \Theta 126 | $$ 127 | -------------------------------------------------------------------------------- /常用LaTex.md: -------------------------------------------------------------------------------- 1 | \wedge 2 | $$ 3 | \wedge 4 | $$ 5 | \vee 6 | $$ 7 | \vee 8 | $$ 9 | \neg 10 | $$ 11 | \neg 12 | $$ 13 | \equiv 14 | $$ 15 | \equiv 16 | $$ 17 | \Leftrightarrow 18 | $$ 19 | \Leftrightarrow 20 | $$ 21 | \forall 22 | $$ 23 | \forall 24 | $$ 25 | \exists 26 | $$ 27 | \exists 28 | $$ 29 | 30 | \rightarow 31 | $$ 32 | \rightarrow 33 | $$ 34 | 35 | \oplus 36 | $$ 37 | \oplus 38 | $$ 39 | \textbf{T} 40 | $$ 41 | \textbf{T} 42 | $$ 43 | {内容}_{下标} 44 | $$ 45 | {内容}_{下标} 46 | $$ 47 | {内容}^{上标} 48 | $$ 49 | {内容}^{上标} 50 | $$ 51 | \therefore 52 | $$ 53 | \therefore 54 | $$ 55 | \frac{上面}{下面} 56 | $$ 57 | \frac{上面}{下面} 58 | $$ 59 | \tag{打tag} 60 | $$ 61 | \tag{打tag} 62 | $$ 63 | 多行公式设置对齐方式 64 | 65 | ```latex 66 | \begin{eqnarray*} 67 | x^n+y^n &=& z^n \tag{1.4} \\ 68 | x+y &=& z \tag{1.5} 69 | \end{eqnarray*} 70 | ``` 71 | 72 | $$ 73 | \begin{eqnarray*} 74 | x^n+y^n &=& z^n \tag{1.4} \\ 75 | x+y &=& z \tag{1.5} 76 | \end{eqnarray*} 77 | $$ 78 | 79 | 列举 80 | 81 | ```la 82 | \begin{cases} 83 | \end{cases} 84 | ``` 85 | 86 | $$ 87 | \begin{cases} 88 | \end{cases} 89 | $$ 90 | 91 | -------------------------------------------------------------------------------- /常用LaTex3.md: -------------------------------------------------------------------------------- 1 | \sqrt{开根号} 2 | $$ 3 | \sqrt{开根号} 4 | $$ 5 | 6 | \binom{上面}{下面} 7 | $$ 8 | \binom{上面}{下面} 9 | $$ 10 | -------------------------------------------------------------------------------- /归谬证明.md: -------------------------------------------------------------------------------- 1 | # 归谬证明 2 | 3 | 为了要证明一个结论为假,首先先假设其为真,然后使用该假设进行推论,直到得到一个错误的结论,则证明假设为假,类似: 4 | $$ 5 | p\ \rightarrow\ q 6 | $$ 7 | 当 q 为假时,p也为假,结论才为真。 8 | 9 | 例子: 10 | $$ 11 | \sqrt{2}\ 为无理数 12 | $$ 13 | 证明过程: 14 | $$ 15 | 首先假设 \sqrt{2}为有理数,则 \\ 16 | \exists p \exists q \in {N}^{+}\ 且\ gcd(p,q)=1,使得 \sqrt{2}=\frac{p}{q},两边平方\\ 17 | 2=\frac{{p}^{2}}{{q}^{2}}\\ 18 | {p}^{2}=2{q}^{2}\\ 19 | 则 p\ 含有因素2,即 p可以写成 p=2k的形式,带入上面的式子中:\\ 20 | 4{k}^{2}=2{q}^{2},约掉一个2之后,\\ 21 | 2{k}^{2}={q}^{2},同理,q中也有一个因素2,则\ gcd(p,q)=2,这跟上面的假设矛盾,所以结论为假,即开始的假设为假。 22 | $$ 23 | 这里可能有疑问,证明过程中的因素2哪来的?这里其实有个很别扭的地方,就是我知道p当中不可能有2的因素,但是换个角度,假如是真的有理数,则会好理解很多: 24 | $$ 25 | p=8,q=2,则 \frac{8}{2}=4,\ \frac{{8}^{2}}{{2}^{2}}={4}^{2}\\ 26 | {8}^{2}=16 \cdot\ {2}^{2} \\ 27 | 那么我们会很容易理解 8= \frac{1}{2} \cdot\ 16 28 | $$ 29 | 但是在上面中,因为根号2不是有理数,所以我主观上就感觉这一块证明很别扭。 30 | 31 | -------------------------------------------------------------------------------- /有趣的概率问题.md: -------------------------------------------------------------------------------- 1 | # 有趣的概率问题 2 | 3 | ## 蒙地厅大厦的3门难题 4 | 5 | > 有3扇门,其中只有1扇门后面有奖金,主持人知道是哪一扇门。 6 | > 7 | > 游戏开始时,你需要首先选择一扇,然后主持人会打开一扇没有奖金的门,这个时候你有第二次选择的权利,你是否会选择更换你的选择? 8 | 9 | --------------------- 10 | 11 | 在说这道题之前,在漫改电视剧《欺诈游戏》中有个很有意思的扑克游戏:[感兴趣可以到B站看](https://www.bilibili.com/video/BV1mt411176C) 12 | 13 | > 在一个不可见的袋子里有2张牌,其中1张两面花色都一致,称为暗牌,另一张背面与暗牌的花色一致,正面是天使的画像,称为亮牌。 14 | > 15 | > 游戏开始时,你从中抽出一张来,这个时候双方开始下注,胜者可以获取所有赌注。 16 | > 17 | > 下注结束后,如果翻过来是亮牌,你胜利,如果是暗牌,则是对方胜利。但是如果翻出来时就确定了牌的种类,则本局作废。 18 | 19 | 问,这游戏你和对方获胜的概率一致吗? 20 | 21 | 答案不是,因为如果你只看你能抽到的牌,那么自然是50%,但是如果按照摆到桌子上的结果来看的话,那么就有4种情况: 22 | 23 | - 亮牌的正面:平局 24 | - 亮牌的背面:胜利 25 | - 暗牌的正面:失败 26 | - 暗牌的背面:失败 27 | 28 | 但是你注意看,当你抽中**亮牌的正面**时,就知道了这张牌,本局作废,所以你的对手的胜率是你的2倍。 29 | 30 | ----------------- 31 | 32 | 同样的道理,在上面的概率题中,你也不能只看最终的成功概率为1/3。这是我摘自知乎中的一个回答,我觉得是最容易理解的: 33 | 34 | > 有三扇门,其中一扇车门,两扇羊门。嘉宾a选定一扇门,剩下的两扇门都是嘉宾b的。那么你要当嘉宾a还是嘉宾b? 35 | 36 | 我觉得很多人都会选择嘉宾b,因为无论怎么看嘉宾a的风险都更高,毕竟2/3的概率会选择羊门。 37 | 38 | ## 生日问题 39 | 40 | > 如果要求房间中至少2个人有相同生日的概率大于1/2,那么所需的最少是多少人? 41 | 42 | 首先假设一年总天数是366天的固定值。 43 | $$ 44 | 其中随便2个人生日不是同一天的概率是 \frac{365}{366} \\ 45 | 其中随便3个人生日不是同一年的概率是 \frac{365}{366} \cdot \frac{364}{366} \\ 46 | \vdots \\ 47 | 其中随便n个人生日不是同一天的概率是 P_n=\frac{365}{366} \cdot \frac{364}{366} \cdots \frac{366-(n-1)}{366}\\ 48 | 则其中随便n个人生体是同一天的概率是 1-P_n > 0.5 \\ 49 | $$ 50 | 其中书上说可以通过微积分的知识来算,或者可以手算,所以我在这里就公布一下答案:n=23 51 | 52 | ### 拉姆赛数:R(m,n) 53 | 54 | 啥是拉姆塞数呢?举个例子就是,假设R(m,n)=x,即在 x 个点中,m个点是互相连接的,**或者**n个点是不互相连接的,能实现这个前提的最小的x的值,就是R(m,n)。 55 | 56 | 比如R(3,3)=6。 57 | 58 | ![](https://tva1.sinaimg.cn/large/008eGmZEgy1gmph2wm9z7j30kt0il0te.jpg) 59 | 60 | 其中分别展示了在0根线,1根线,2根线,3根线的情况下,上面的结论都是成立的。 61 | 62 | 或者另一个更加常见的说法是: 63 | 64 | > 在一个6人的派对上,至少有3人是朋友,或者3人不互相认识。 65 | 66 | -------------------------------------------------------------------------------- /沃舍尔算法.md: -------------------------------------------------------------------------------- 1 | # 沃舍尔算法 2 | 3 | 沃舍尔算法的本质很简单,既然是传递闭包,那么对于像`(3,1),(1,2)`这样的关系,一定有一个`(3,2)`的关系,所以我们要做的就是把这些关系补气就行。 4 | 5 | [参考油管视频](https://www.youtube.com/watch?v=fQ8wKewQtDs) 6 | 7 | 代码: 8 | 9 | ```php 10 | $line){ 25 | foreach($line as $columnNumber=>$data){ 26 | if($lineNumber==$n && $data){ 27 | $returnColumnNumber[]=$columnNumber; 28 | } 29 | if($columnNumber==$n && $data){ 30 | $returnLineNumber[]=$lineNumber; 31 | } 32 | } 33 | } 34 | foreach($returnLineNumber as $lineNumber){ 35 | foreach($returnColumnNumber as $columnNumber){ 36 | $map[$lineNumber][$columnNumber]=1; 37 | } 38 | } 39 | } 40 | 41 | $map=[ 42 | 0=>[1,0,1], 43 | 1=>[0,1,0], 44 | 2=>[1,1,0] 45 | ]; 46 | 47 | $newMap=WasherAlgorithm($map); 48 | 49 | print_r($newMap); 50 | 51 | ``` 52 | 53 | 上面特意使用这个矩阵,是因为和[之前采用关系的幂来求传递闭包](https://blog.csdn.net/YQXLLWY/article/details/113487097)时采用相同的数据,好验证结果,结果发现两者结果是一样的。 54 | 55 | -------------------------------------------------------------------------------- /离散数学.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiddleSunshine/DiscreteMath/1cc894159d7cdecd86e2b1466d98ce0372b60d6d/离散数学.graffle -------------------------------------------------------------------------------- /第1章 基础:逻辑和证明 2.md: -------------------------------------------------------------------------------- 1 | # 1.5 嵌套量词 2 | 3 | 即量词作用域的叠加。如 4 | $$ 5 | \forall x \exists y\ (x+y=0) 6 | $$ 7 | 即对于所有x,都存在一个y,使得x+y=0。 8 | 9 | 再来对于我们熟悉的加法交换律,可以采用下面的形式来表示: 10 | $$ 11 | \forall x \forall y\ (x+y=y+x) 12 | $$ 13 | 14 | #### 注意事项:量词的顺序 15 | 16 | $$ 17 | 式子1\ \forall x \forall y\ (x+y=y+x) \\ 18 | 式子2\ \forall y \forall x\ (x+y=y+x) 19 | $$ 20 | 21 | 在上面的式子1和式子2中,前面量词的交换是不会产生影响的,两个命题都为真。但是下面这种就不行了: 22 | $$ 23 | 式子1\ \forall x \exists y (x+y=0) \\ 24 | 式子2\ \exists y \forall x (x+y=0) 25 | $$ 26 | 27 | 式子1是真命题,对于所有x,都存在一个y,使得x+y=0。 28 | 29 | 但是式子2的含义则是,存在一个y,使得所有x能满足y+x=0,就我目前的知识水平来说,感觉这种数不存在。 30 | 31 | 也有一种常见表现形式: 32 | $$ 33 | P(x,y)代表x+y=0,\forall x \exists y P(x,y) 34 | $$ 35 | 36 | # 1.6 推理规则 37 | 38 | $$ 39 | \frac{ 40 | p \rightarrow q \\ 41 | p 42 | }{ 43 | \therefore q 44 | } 45 | $$ 46 | 47 | 在推理过程中,需要保证前提都为真,在前提为真的情况下,结论必定为真。 48 | 49 | ------------------ 50 | 51 | #### 假言推理 52 | 53 | $$ 54 | \frac{ 55 | p\\ 56 | p \rightarrow q 57 | }{ 58 | \therefore q 59 | } 60 | $$ 61 | 62 | #### 取拒式 63 | 64 | $$ 65 | \frac{ 66 | \neg q \\ 67 | p \rightarrow q 68 | }{ 69 | \therefore \neg p 70 | } 71 | $$ 72 | 73 | #### 假言三段论 74 | 75 | $$ 76 | \frac{ 77 | p \rightarrow q \\ 78 | q \rightarrow r 79 | }{ 80 | \therefore p \rightarrow r 81 | } 82 | $$ 83 | 84 | #### 析取三段论 85 | 86 | $$ 87 | \frac{ 88 | p \vee q \\ 89 | \neg p 90 | }{ 91 | \therefore q 92 | } 93 | $$ 94 | 95 | #### 附加论 96 | 97 | $$ 98 | \frac{p}{\therefore p \vee q} 99 | $$ 100 | 101 | #### 化简率 102 | 103 | $$ 104 | \frac{p \wedge q}{\therefore p} 105 | $$ 106 | 107 | #### 合取率 108 | 109 | $$ 110 | \frac{p\\q}{\therefore p \wedge q} 111 | $$ 112 | 113 | #### 消解率 114 | 115 | $$ 116 | \frac{ 117 | p \vee q \\ 118 | \neg p \vee r 119 | }{ 120 | \therefore q \vee r 121 | } 122 | $$ 123 | 124 | ### 量化命题的推理规则 125 | 126 | #### 全称实例 127 | 128 | $$ 129 | \frac{ 130 | \forall x P(x) 131 | }{ 132 | \therefore P({x}_{0}) 133 | } 134 | $$ 135 | 136 | #### 全称引入 137 | 138 | $$ 139 | \frac{ 140 | P(c),c为任意值 141 | }{ 142 | \therefore \forall x P(x) 143 | } 144 | $$ 145 | 146 | #### 存在实例 147 | 148 | $$ 149 | \frac{ 150 | \exists x P(x) 151 | }{ 152 | \therefore p(c),c为某一特定值 153 | } 154 | $$ 155 | 156 | #### 存在引入 157 | 158 | $$ 159 | \frac{ 160 | P(c),对于某个值c 161 | }{ 162 | \exists x P(x) 163 | } 164 | $$ 165 | 166 | # 1.7 证明导论 167 | 168 | #### 直接证明 169 | 170 | $$ 171 | \frac{ 172 | p \\ 173 | q 174 | }{ 175 | \therefore p \rightarrow q 176 | } 177 | $$ 178 | 179 | 例子: 180 | $$ 181 | p:n是奇数时 \\ 182 | q: {n}^{2} 也是是奇数 183 | $$ 184 | 只需要证明在p为真的情况下,q也肯定为真,就能证明上面的命题为真。 185 | 186 | #### 间接证明 187 | 188 | $$ 189 | p \rightarrow q \equiv 190 | \neg q \rightarrow \neg p 191 | $$ 192 | 193 | 这里补充一下上面的内容的真值表: 194 | 195 | | p | q | 逆q | 逆p | p蕴含q | 逆q蕴含逆p | 196 | | ---- | ---- | ---- | ---- | ------ | ---------- | 197 | | 0 | 0 | 1 | 1 | 1 | 1 | 198 | | 0 | 1 | 0 | 1 | 1 | 1 | 199 | | 1 | 0 | 1 | 0 | 0 | 0 | 200 | | 1 | 1 | 0 | 0 | 1 | 1 | 201 | 202 | $$ 203 | \frac{ 204 | \neg q\\ 205 | \neg p \\ 206 | \neg q \rightarrow \neg p 207 | }{ 208 | \therefore p \rightarrow q 209 | } 210 | $$ 211 | 212 | 213 | 214 | 例子: 215 | $$ 216 | p:3*n+2 是奇数 \\ 217 | q:n是奇数 218 | $$ 219 | 换个思路: 220 | $$ 221 | \neg q:n不是奇数 \\ 222 | \neg p:3*n+2 不是奇数 223 | $$ 224 | 证明: 225 | $$ 226 | k \in \textbf{N} \\ 227 | 3*n+2 = 2*k \\ 228 | n+2*n = 2*(k-1) \\ 229 | 2*n 不是奇数,2*(k-1)也不是奇数,所以n肯定不是奇数 \\ 230 | $$ 231 | 232 | #### 归谬证明 233 | 234 | $$ 235 | \frac{ 236 | \neg p \rightarrow (r \wedge \neg r) 237 | }{ 238 | \therefore p 239 | } 240 | $$ 241 | 242 | 243 | 244 | 这个我也没搞懂。 245 | 246 | # 1.8 证明的方法和策略 247 | 248 | #### 穷举证明 249 | 250 | 例子: 251 | $$ 252 | n \in {N}_{+},n <=4 时,{(n+1)}^{3}>={3}^{n} 253 | $$ 254 | 不用管,直接拿n=1,2,3,4往里代就行了。 255 | 256 | #### 分情形证明 257 | 258 | 例子: 259 | $$ 260 | n \in \textbf{N},\ {n}^{2}>=n 261 | $$ 262 | 证明: 263 | $$ 264 | \begin{cases} 265 | n=0&,0=0 \\ 266 | n>0&,n>=1 \\ 267 | n<0&,{n}^{2}>0 268 | \end{cases} 269 | $$ 270 | 271 | #### 存在性证明 272 | 273 | #### 唯一性证明 274 | 275 | 276 | 277 | -------------------------------------------------------------------------------- /第1章 基础:逻辑和证明.md: -------------------------------------------------------------------------------- 1 | # 简介 2 | 3 | 我为什么要写这个呢?因为我信奉一点,纸质材料肯定会丢失的,所以我在尽量将内容转化成电子文档。至于为社么不选择OneNote,有道云笔记之类的,就是想以博客更新的方式催促自己可以坚持下去,过个1年,2年来看自己当初的付出,那是真的会很爽的,特别是希望自己到时候能感受到自己现在的努力或者犯傻。 4 | 5 | 再来是下面的内容来自哪里呢?来自《离散数学及其应用》。 6 | 7 | 接着是下面的公式是怎么写的呢?LaTex。 8 | 9 | 最后就是下面的内容类似我的读书笔记之类的,让我以后需要的时候可以拿来翻翻,所以类似总结,说明很少。 10 | 11 | # 1.1 命题逻辑 12 | 13 | $$ 14 | \wedge 合取 15 | \\ 16 | \vee 析取 17 | $$ 18 | 19 | $$ 20 | p \oplus q\ 真值表 21 | $$ 22 | 23 | | p | q | 异或 | 24 | | ---- | ---- | ---- | 25 | | T | T | F | 26 | | T | F | T | 27 | | F | T | T | 28 | | F | F | F | 29 | 30 | $$ 31 | p \longrightarrow q\ 真值表 / 蕴含 32 | $$ 33 | 34 | | p | q | 条件语句 | 35 | | ---- | ---- | -------- | 36 | | T | T | T | 37 | | T | F | F | 38 | | F | T | T | 39 | | F | F | T | 40 | 41 | 可以结合下面的例子来理解: 42 | 43 | - p:张生如果高中 44 | - q:张生娶崔莺莺 45 | 46 | 问,在什么情况下张生食言了? 47 | 48 | | 情况 | p | q | 条件语句 | 49 | | ------------| ------------ | -------------- | -------------------------------- | 50 | | 1 | 张生高中 | 娶崔莺莺 | 张生没有食言 | 51 | | 2 | 张生高中 | 没有娶崔莺莺 | 张生食言了 | 52 | | 3 | 张生没有高中 | 娶崔莺莺 | 张生没有食言,他娶了崔莺莺 | 53 | | 4 | 张生没有高中 | 也没有娶崔莺莺 | 张生本质上没有食言,他的确没高中 | 54 | 55 | 其中可能有人会在3和4之间纠结,因为觉得3也应该算张生食言了,但是和情况2比较,你觉得哪个更像张生食言了? 56 | 57 | ### 逻辑运算优先级 58 | 59 | 可以这么理解,逆类似负数的符号,优先级肯定是最高的。 60 | 61 | 接下来的就是合取优先级高于析取。 62 | 63 | 最后就是蕴含。 64 | 65 | # 1.3 命题等价式 66 | #### 衡等律 67 | 68 | $$ 69 | p\wedge \textbf{T} \equiv p \\ p \vee \textbf{F} \equiv p 70 | $$ 71 | 72 | 73 | 74 | #### 支配率 75 | 76 | $$ 77 | p \vee \textbf{T} \equiv \textbf{T} \\ 78 | p \wedge \textbf{F} \equiv \textbf{F} 79 | $$ 80 | 81 | #### 幂等律 82 | 83 | $$ 84 | p \wedge p \equiv p \\ 85 | p \vee p \equiv p 86 | $$ 87 | 88 | #### 双重否定率 89 | 90 | $$ 91 | \neg ( \neg P ) \equiv p 92 | $$ 93 | 94 | #### 交换律 95 | 96 | $$ 97 | p \vee q \equiv q \vee p \\ 98 | p \wedge q \equiv q \wedge p 99 | $$ 100 | 101 | #### 结合律 102 | 103 | $$ 104 | ( p \wedge q ) \wedge r \equiv p \wedge ( q \wedge r ) \\ 105 | ( p \vee q ) \vee r \equiv p \vee ( q \vee r ) 106 | $$ 107 | 108 | #### 分配率 109 | 110 | $$ 111 | (p \vee r) \wedge (q \vee r) \equiv ( p \wedge q ) \vee r \\ 112 | (p \wedge r) \vee (q \wedge r) \equiv ( p \vee q ) \wedge r 113 | $$ 114 | 115 | #### 德 摩根率 116 | 117 | $$ 118 | \neg ( p \wedge q ) \equiv (\neg p) \vee (\neg q) \\ 119 | \neg ( p \vee q ) \equiv (\neg p) \wedge (\neg q) 120 | $$ 121 | 122 | #### 吸收率 123 | 124 | $$ 125 | p \vee (p \wedge q) \equiv p \\ 126 | p \wedge (p \vee q) \equiv p 127 | $$ 128 | 129 | #### 否定率 130 | 131 | $$ 132 | p \vee \neg p \equiv \textbf{T} \\ 133 | p \wedge \neg p \equiv \textbf{F} 134 | $$ 135 | 136 | # 1.4 量词和谓词 137 | 138 | #### 量词 139 | 140 | $$ 141 | \forall x\ \textbf{P}(x) 142 | $$ 143 | 144 | **全称量词**:对于所有`x`,`P(x)`都为真。但是如果存在一个`x`,使得`P(x)`为假,上面的命题就是假的。 145 | $$ 146 | \exists x \textbf{P}(x) 147 | $$ 148 | **存在量词**:至少存在一个`x`,使得`P(x)`为真。当对于每一个`x`,`P(x)`为真时,上面的命题就是假的。 149 | $$ 150 | \exists ! \\ 151 | {\exists}_{1} 152 | $$ 153 | 上面的代表唯一性量词,代表`x`仅有一个值能使`P(x)`为真。 154 | 155 | #### 优先级注意事项 156 | 157 | $$ 158 | \forall x \textbf{P}(x) \vee \textbf{Q}(x) \equiv (\forall x \textbf{P}(x))\ \vee\ (\textbf{Q}(x)) \\ 159 | 而不是\\ 160 | \forall x (\textbf{P}(x)\ \vee\ \textbf{Q}(x))) 161 | $$ 162 | 163 | 还有一种常见的表现形式: 164 | $$ 165 | \forall x < 0\ ({x}^{2}>0) 166 | $$ 167 | 代表的含义就是对于所有的`x<0`,`x`的平方大于0。 168 | 169 | #### 量词的否定,即量词的德 摩根率 170 | 171 | $$ 172 | \neg \forall x \textbf{P}(x)\ \equiv \exists x\ \neg\textbf{P}(x) 173 | $$ 174 | 175 | 上面的含义就是对于所有x,P(x)为真的逆就是存在x,使得p(x)为假。 176 | 177 | 同理。 178 | $$ 179 | \neg \exists x \textbf{P}(x) \equiv \forall x \neg\textbf{P(x)} 180 | $$ 181 | 存在x,使得p(x)为真的逆就是没有x,使得p(x)为真,即对于所有x,p(x)为假。 182 | 183 | -------------------------------------------------------------------------------- /第2章 集合、函数、序列、求和与矩阵.md: -------------------------------------------------------------------------------- 1 | # 2.1 集合 2 | 3 | #### 子集 4 | 5 | $$ 6 | x \in {N}_{+} \\ 7 | x \subseteq {N}\\ 8 | x是\textbf{N}的子集 9 | $$ 10 | 11 | #### 空集 12 | 13 | $$ 14 | \begin{eqnarray*} 15 | S 是任意集合 \\ 16 | \emptyset \subseteq S \tag{2.1.1} \\ 17 | S \subseteq S \tag{2.1.2} 18 | \end{eqnarray*} 19 | $$ 20 | 21 | #### 基数:集合中元素的个数 22 | 23 | $$ 24 | \left\vert S \right\vert\ 代表集合的基数 25 | $$ 26 | 27 | 例子: 28 | $$ 29 | S 代表小于10的正整数奇数,则\ \left\vert S \right\vert = 5。 30 | $$ 31 | 32 | #### 幂集:集合S所有子集的集合 33 | 34 | 例子: 35 | $$ 36 | {0,1,2}的幂集是\\ 37 | \mathcal{P}(\{0,1,2\})=\{\\ 38 | \emptyset,\\ 39 | \{0\},\{1\},\{2\},\\ 40 | \{0,1\},\{0,2\},\{1,2\},\\ 41 | \{1,2,3\}\\ 42 | \} 43 | $$ 44 | 45 | 46 | #### 笛卡尔积 47 | 48 | 直接来一个例子会好理解很多: 49 | $$ 50 | 集合A=\{a,b\}\\ 51 | 集合B=\{0,1,2\}\\ 52 | A和B的笛卡尔积就是:\\ 53 | A \times B = \{\\ 54 | \{a,0\},\{a,1\},\{a,2\}\\ 55 | \{b,0\},\{b,1\},\{b,2\}\\ 56 | \} 57 | $$ 58 | 两个集合的笛卡尔积也可以采用下面的公式表示: 59 | $$ 60 | A \times B = \{(a,b)\mid a \in A \wedge\ b \in B\} 61 | $$ 62 | 63 | #### 量词和集合 64 | 65 | 例子: 66 | $$ 67 | \forall x \in \textbf{R}\ ({x}^{2}>=0) \\ 68 | \exists x \in \textbf{Z}\ ({x}^{2}=1) 69 | $$ 70 | 真值集和量词 71 | $$ 72 | \{\ x \in D | P(x)\ \}\ 代表的含义是,对于集合D中的任何一个元素x,P(x)都为真。 73 | $$ 74 | 75 | # 2.2 集合运算 76 | 77 | 集合中的一些概念。 78 | 79 | #### 并集 80 | 81 | $$ 82 | A \cup B 83 | $$ 84 | 85 | #### 交集 86 | 87 | $$ 88 | A \cap B 89 | $$ 90 | 91 | #### 差集 92 | 93 | $$ 94 | x \in (A - B),该集合代表该元素属于集合A,但是不属于集合B 95 | $$ 96 | 97 | #### 补集 98 | 99 | $$ 100 | U表示全集,\bar{A}代表A的补集,即 U-A 101 | $$ 102 | 103 | 集合的一些衡等式。 104 | 105 | #### 恒等律 106 | 107 | $$ 108 | A \cap U = A \\ 109 | A \cup \emptyset = A 110 | $$ 111 | 112 | #### 支配率 113 | 114 | $$ 115 | A \cup U = U \\ 116 | A \cap \emptyset = \emptyset 117 | $$ 118 | 119 | #### 幂等律 120 | 121 | $$ 122 | A \cap A = A \\ 123 | A \cup A = A 124 | $$ 125 | 126 | #### 补律 127 | 128 | $$ 129 | \overline{\bar{A}}=A 130 | $$ 131 | 132 | #### 交换律 133 | 134 | $$ 135 | A \cap B = B \cap A \\ 136 | A \cup B = B \cup A 137 | $$ 138 | 139 | #### 结合律 140 | 141 | $$ 142 | A \cup (B \cup C) = (A \cup B) \cup C \\ 143 | A \cap (B \cap C) = (A \cap B) \cap C 144 | $$ 145 | 146 | #### 分配率 147 | 148 | $$ 149 | \begin{eqnarray*} 150 | A \cup (B \cap C)=(A \cup B) \cap (A \cup C) \tag{1}\\ 151 | A \cap (B \cup C)=(A \cap B) \cup (A \cap C) \tag{2} 152 | \end{eqnarray*} 153 | $$ 154 | 155 | A:一杯有芋圆的奶茶 156 | 157 | B:一杯有珍珠的奶茶 158 | 159 | C:一杯有波霸的奶茶 160 | 161 | 式子1: 162 | 163 | 左边:一杯一定有芋圆,但是肯定没有珍珠和波霸的奶茶 164 | 165 | 右边:一杯一定有芋圆和珍珠的奶茶,一杯一定有芋圆和波霸的奶茶,这两杯奶茶的交集:一定有芋圆,但是肯定没有珍珠和波霸 166 | 167 | 式子2: 168 | 169 | 左边:一杯奶茶里肯定没有芋圆,珍珠和波霸 170 | 171 | 右边:一杯肯定没有芋圆和珍珠的奶茶,再混上一杯肯定没有芋圆和波霸的奶茶,即一杯肯定没有芋圆和珍珠,以及波霸的奶茶 172 | 173 | #### 德 摩根率 174 | 175 | $$ 176 | \begin{eqnarray*} 177 | \overline{A \cap B} = \overline{A} \cup \overline{B} \tag{3} \\ 178 | \overline{A \cup B} = \overline{A} \cap \overline{B} \tag{4} 179 | \end{eqnarray*} 180 | $$ 181 | 182 | 式子3: 183 | 184 | 左边:一杯可能有芋圆或者珍珠的奶茶 185 | 186 | 右边:一杯没有芋圆的奶茶再混入一杯没有珍珠的奶茶 187 | 188 | 式子4: 189 | 190 | 左边:一杯肯定没有芋圆和珍珠的奶茶 191 | 192 | 右边:一杯肯定没有芋圆的奶茶,和一杯肯定没有珍珠的奶茶的交集,那就肯定没有芋圆和珍珠的奶茶 193 | 194 | #### 吸收率 195 | 196 | $$ 197 | \begin{eqnarray*} 198 | A \cup (A \cap B) = A \tag{5} \\ 199 | A \cap (A \cup B) = A \tag{6} 200 | \end{eqnarray*} 201 | $$ 202 | 203 | #### 互补率 204 | 205 | $$ 206 | A \cup \bar{A} = U \\ 207 | A \cap \bar{A} = \emptyset 208 | $$ 209 | 210 | #### 一组集合的交集和并集 211 | 212 | $$ 213 | {A}_{0} \cup {A}_{1} \cup {A}_{2} \cup {A}_{3} \cup \cdots {A}_{n} = 214 | \begin{gathered} 215 | n \\ 216 | \bigcup \\ 217 | i=0 218 | \end{gathered} 219 | {A}_{i} 220 | $$ 221 | 222 | $$ 223 | {A}_{0} \cap {A}_{1} \cap {A}_{2} \cap {A}_{3} \cap \cdots {A}_{n} = 224 | \begin{gathered} 225 | n \\ 226 | \bigcap \\ 227 | i=0 228 | \end{gathered} 229 | {A}_{i} 230 | $$ 231 | 232 | #### 多重集合 233 | 234 | 采用下面的形式记录一个元素在集合中出现的次数: 235 | $$ 236 | \{{m}_{0}\bullet{a}_{0},{m}_{1}\bullet{a}_{1},{m}_{2}\bullet{a}_{2},\dots\} 237 | $$ 238 | 239 | # 2.3 函数 240 | 241 | 不按照书上的严格定义,简单点来说函数就是一个集合到另一个集合的一种转换关系。但是一定要A中的元素仅能对应到B中的一个元素。 242 | $$ 243 | f:A \rightarrow B \\ 244 | A 是 f 的定义域 \\ 245 | B 是 f 的陪域 \\ 246 | 如果 f(a)=b \\ 247 | a 是 b 的原像 \\ 248 | b 是 a 的像 249 | $$ 250 | 251 | ----------- 252 | 253 | $$ 254 | 如果 {f}_{1}和{f}_{2}是A到R的函数,那么:\\ 255 | \forall x \in A\\ 256 | {f}_{1}(x)+{f}_{2}(x)=({f}_{1}+{f}_{2})(x) \\ 257 | {f}_{1}(x){f}_{2}(x)=({f}_{1}{f}_{2})(x) 258 | $$ 259 | 260 | #### 一对一映射 261 | 262 | 即A中的元素和B中的元素通过f是一一对应的。 263 | 264 | #### 映上函数 / 满射 265 | 266 | $$ 267 | \forall y \exists x (f(y)=x) 268 | $$ 269 | 270 | 即对于集合B中的任何一个元素,都存在一个A中的元素与之对应。 271 | 272 | 注意事项: 273 | 274 | - A 中的元素不用都对应到B中的元素 275 | - A中的元素可以多个元素对应到B中的一个元素 276 | - 一对一不一定是映上函数,因为可能有B中的元素没有对应到。 277 | 278 | #### 双射函数 279 | 280 | 即改函数即是一对一函数,又是映上函数。 281 | 282 | #### 反函数 283 | 284 | 如果f是一个双射函数,则其存在反函数。 285 | $$ 286 | f(a)=b \\ 287 | {f}^{-1}(b)=a 288 | $$ 289 | 290 | #### 函数的合成 291 | 292 | $$ 293 | g是集合A到集合B的函数,f是集合B到集合C的函数,函数f和g的合成记做 f \circ g,即\\ 294 | \forall a \in A,(g \circ f)(a)=f(g(a)) 295 | $$ 296 | 297 | #### 上,下取整函数 298 | 299 | $$ 300 | \textbf{Z}代表整数,\\ 301 | \lceil x \rceil\ 代表\ a \in \textbf{Z}, a>=x \\ 302 | \lfloor x \rfloor\ 代表\ a \in \textbf{Z},a<=x 303 | $$ 304 | 305 | # 2.4 序列和求和 306 | 307 | #### 序列求和 308 | 309 | $$ 310 | \sum^{j=m}_{n} {a}_{j} 311 | $$ 312 | 313 | #### 几何序列求和 314 | 315 | $$ 316 | \sum^{n}_{j=0} a{r}^{j}= 317 | \begin{cases} 318 | \frac{ 319 | a{r}^{n+1}-a 320 | }{ 321 | r-1 322 | }& r \neq 1 \\ 323 | (n+1)a& r=1 324 | \end{cases} 325 | $$ 326 | 327 | # 2.5 集合的基数 328 | 329 | $$ 330 | 如果一个无限集S是可数的,就使用阿里夫零来代表其基数:{\aleph}_{0},写作 |S|={\aleph}_{0} 331 | $$ 332 | 333 | 什么叫做无限集S是可数的呢?就是可以把集合中的元素排列成序列。(具体内容没搞懂。。。。。。) 334 | 335 | # 2.6 矩阵 336 | 337 | $$ 338 | m \times n 代表的是一个 m 行,n列的矩阵 \\ 339 | A=[{a}_{ij}]\ 代表的是矩阵中第i行第j列的元素。 340 | $$ 341 | 342 | #### 矩阵求和 343 | 344 | $$ 345 | A + B = [{a}_{ij}+{b}_{ij}] 346 | $$ 347 | 348 | 例子: 349 | $$ 350 | \begin{vmatrix} 351 | 1&2&3 \\ 352 | 4&5&6 353 | \end{vmatrix} 354 | + 355 | \begin{vmatrix} 356 | 1&2&3 \\ 357 | 4&5&6 358 | \end{vmatrix} 359 | = 360 | \begin{vmatrix} 361 | 2&4&6 \\ 362 | 8&10&12 363 | \end{vmatrix} 364 | $$ 365 | 366 | #### 矩阵乘法 367 | 368 | 例子: 369 | 370 | $$ 371 | \begin{vmatrix} 372 | 1&0&4\\ 373 | 2&1&1\\ 374 | 3&1&0\\ 375 | 0&2&2 376 | \end{vmatrix} 377 | \begin{vmatrix} 378 | 2&4\\ 379 | 1&1\\ 380 | 3&0\\ 381 | \end{vmatrix} 382 | = 383 | \begin{vmatrix} 384 | 1*2+0*1+4*3 & 1*4+0*1+4*0 \\ 385 | 2*2+1*1+1*3 & 2*4+1*1+1*0 \\ 386 | 3*2+1*1+0*3 & 3*4+1*1+0*0 \\ 387 | 0*2+2*1+2*3 & 0*4+2*1+2*0 \\ 388 | \end{vmatrix} 389 | = 390 | \begin{vmatrix} 391 | 14&4\\ 392 | 8&9\\ 393 | 7&13\\ 394 | 8&2 395 | \end{vmatrix} 396 | $$ 397 | 398 | #### 克罗克内积 399 | 400 | $$ 401 | {I}_{n}=[{\delta}_{ij}],如果 i=j,{\delta}_{ij}=1,如果 i \neq j,{\delta}_{ij}=0 \\ 402 | \\ 403 | \begin{vmatrix} 404 | 1&0&0& \cdots & 0\\ 405 | 0&1&0& \cdots & 0\\ 406 | 0&0&1& \cdots & 0\\ 407 | \vdots&\vdots&\vdots&\vdots&\vdots\\ 408 | 0&0&0&0&1 409 | \end{vmatrix} 410 | \\ 411 | A 是一个 m \times n 的矩阵,则 A \times {I}_{m} = A 412 | $$ 413 | 414 | #### 转置 415 | 416 | $$ 417 | 矩阵 A 的转置记录为{A}^{T},即交换行和列。\\ 418 | \begin{vmatrix} 419 | 14&4\\ 420 | 8&9\\ 421 | 7&13\\ 422 | 8&2 423 | \end{vmatrix} 424 | 经过转置后 425 | \begin{vmatrix} 426 | 14&8&7&8\\ 427 | 4&9&13&2 428 | \end{vmatrix} 429 | $$ 430 | 431 | #### 对称矩阵:即经过转置后与原矩阵相同的矩阵 432 | 433 | 如下面这个矩阵就是个对称矩阵 434 | $$ 435 | \begin{vmatrix} 436 | 1&1&0\\ 437 | 1&0&1\\ 438 | 0&1&0 439 | \end{vmatrix} 440 | $$ 441 | 442 | #### 矩阵进行“并”和“交”计算 443 | 444 | $$ 445 | A= 446 | \begin{vmatrix} 447 | 1&0&1\\ 448 | 0&1&0 449 | \end{vmatrix}, 450 | B= 451 | \begin{vmatrix} 452 | 0&1&0\\ 453 | 1&1&0 454 | \end{vmatrix} 455 | $$ 456 | 457 | 并: 458 | $$ 459 | A \vee B =\ 460 | \begin{vmatrix} 461 | 1 \vee 0 & 0 \vee 1 & 1 \vee 0 \\ 462 | 0 \vee 1 & 1 \vee 1 & 0 \vee 0 463 | \end{vmatrix} 464 | = 465 | \begin{vmatrix} 466 | 1&1&1\\ 467 | 1&1&0 468 | \end{vmatrix} 469 | $$ 470 | 交: 471 | 472 | $$ 473 | A \wedge B =\ 474 | \begin{vmatrix} 475 | 1 \wedge 0 & 0 \wedge 1 & 1 \wedge 0 \\ 476 | 0 \wedge 1 & 1 \wedge 1 & 0 \wedge 0 477 | \end{vmatrix} 478 | = 479 | \begin{vmatrix} 480 | 0&0&0\\ 481 | 0&1&0 482 | \end{vmatrix} 483 | $$ 484 | 485 | #### 布尔积 486 | 487 | $$ 488 | A 是一个 m \times k的集合,B是一个 k \times n 的集合,A \odot b 代表 A 和 B的布尔积。 489 | $$ 490 | 491 | 例子: 492 | $$ 493 | A= 494 | \begin{vmatrix} 495 | 1&0\\ 496 | 0&1\\ 497 | 1&0 498 | \end{vmatrix}, 499 | B= 500 | \begin{vmatrix} 501 | 1&1&0\\ 502 | 0&1&1 503 | \end{vmatrix} 504 | \\ 505 | A \odot B= 506 | \begin{vmatrix} 507 | (1 \wedge 1) \vee (0 \wedge 0) & (1 \wedge 1) \vee (0 \wedge 1) & (1 \wedge 0) \vee (0 \wedge 1)\\ 508 | (0 \wedge 1) \vee (1 \wedge 0) & (0 \wedge 1) \vee (1 \wedge 1) & (0 \wedge 0) \vee (1 \wedge 1)\\ 509 | (1 \wedge 1) \vee (0 \wedge 0) & (1 \wedge 1) \vee (0 \wedge 1) & (1 \wedge 0) \vee (0 \wedge 1) 510 | \end{vmatrix} 511 | = 512 | \begin{vmatrix} 513 | 1&1&0\\ 514 | 0&1&1\\ 515 | 1&1&0 516 | \end{vmatrix} 517 | $$ 518 | 519 | #### 布尔幂:即集合A的r次布尔积 520 | 521 | $$ 522 | {A}^{[r]}=\underbrace{A \odot A \odot A \cdots A}_{r个A} 523 | $$ 524 | 525 | -------------------------------------------------------------------------------- /第3章 算法.md: -------------------------------------------------------------------------------- 1 | # 3.2 函数的增长 2 | 3 | [参考B站视频](https://www.bilibili.com/video/BV14j411f7DJ?t=670) 4 | 5 | 大O表示法定义: 6 | $$ 7 | 当 x > k 时,|f(x)|<=C|g(x)|,C|g(x)|就记做\ O(g(x)) 8 | $$ 9 | 这个其实很简单,分为2个部分取考虑: 10 | 11 | 1. `f(x)`是什么,即代码会执行多少次。 12 | 13 | 例1: 14 | 15 | ```php 16 | // $n=100; 17 | for($i=1;$i<=$n;$i++){ 18 | print "当前i的值是:".$i.PHP_EOL; 19 | } 20 | ``` 21 | 22 | 问,上面这个函数执行多少次?答:`1+3*n`。`$i=1`是1,`$i<=$n`,`$i++`,`print print "当前i的值是:".$i.PHP_EOL;`各会执行n次,所以总次数为`1+3*n`次,即`f(x)=1+3*n`。 23 | 24 | 然后考虑,当n趋紧于无限大的时候,+1和`*3`对n的值影响到不大,所以大O表示法就可以写成 25 | $$ 26 | f(x)=1+3x=O(x) \\ 27 | 或者用更加习惯的n来替代x \\ 28 | O(n) 29 | $$ 30 | 例2: 31 | 32 | ```php 33 | for($i=1;$i<=$n;$i++){ 34 | for($j=1;$j<=$n;$j++){ 35 | print "当前i和j的值为:({$i},{$j})".PHP_EOL; 36 | } 37 | } 38 | ``` 39 | 40 | 例2中,函数执行了多少次?`n*(3*n+1)+2*n+1`,计算后得到结果: 41 | $$ 42 | 3{n}^{2}+3n+1 43 | $$ 44 | 然后我们设想,n的平方的增加速度会比3n快很多,当n趋近于无限大的时候,上面的函数起主要作用的就是n的平方。 45 | $$ 46 | f(x)=3{n}^{2}+3n+1=O({n}^{2}) 47 | $$ 48 | 上面这两个例子可以总结成下面的这个定理: 49 | $$ 50 | f(x)={a}_{n}{x}^{n}+{a}_{n-1}{x}^{n-1}+{a}_{n-2}{x}^{n-2} \cdots + {a}_{1}{x}^{1}+ {a}_{0}{x}^{0} \\ 51 | {a}_{n} \in Q,\\ 52 | f(x)=Q({x}^{n}) 53 | $$ 54 | 证明过程: 55 | $$ 56 | x>=1时\\ 57 | |f(x)|=|{a}_{n}{x}^{n}+{a}_{n-1}{x}^{n-1}+{a}_{n-2}{x}^{n-2} \cdots + {a}_{1}{x}^{1}+ {a}_{0}{x}^{0}| \\ 58 | <=|{a}_{n}|{x}^{n}+|{a}_{n-1}|{x}^{n-1}+|{a}_{n-2}|{x}^{n-2} \cdots + |{a}_{1}|{x}^{1}+ |{a}_{0}|{x}^{0} \\ 59 | = {x}^{n}({a}_{n}+{a}_{n-1} \times \frac{1}{x} +{a}_{n-2} \times \frac{1}{{x}^{2}} \cdots +{a}_{1} \times \frac{1}{{x}^{n-1}} +{a}_{n} \times \frac{1}{{x}^{n}}) \\ 60 | <= {x}^{n}({a}_{n}+{a}_{n-1}+{a}_{n-2} \cdots {a}_{1}+{a}_{0}) \\ 61 | 即 |f(x)|<=C|g(x)|,g(x)={x}^{n},即 f(x)=O({x}^{n}) 62 | $$ 63 | 至于这里为什么要x>1,是因为执行步骤肯定是存在的,如果没有执行步骤,那么讨论算法复杂度就没有意义了。 64 | 65 | #### 函数组合的增长 66 | 67 | 相加: 68 | $$ 69 | 如果,{f}_{1}=O({g}_{1}(x)),{f}_{2}=O({g}_{2}(x)),\\则({f}_{1}+{f}_{2})(x)=O(g(x)),g(x)=max({g}_{1}(x),{g}_{2}(x)) 70 | $$ 71 | 相乘: 72 | $$ 73 | 如果,{f}_{1}=O({g}_{1}(x)),{f}_{2}=O({g}_{2}(x)),\\则({f}_{1}{f}_{2})(x)=O(g(x)),g(x)=({g}_{1}(x){g}_{2}(x)) 74 | $$ 75 | 76 | #### 函数执行的下限:大欧米伽表示法 77 | 78 | $$ 79 | 当 x > k 时,|f(x)|>=C|g(x)|,C|g(x)|就记做\ \Omega(g(x)) 80 | $$ 81 | 82 | 上面是考虑x趋于无限大,这里则不是,具体根据定义来推倒吧,或者可以说是算法的一般情况。 83 | 84 | #### 当函数的大O表示法和大欧米伽相同时:大西塔 85 | 86 | $$ 87 | f(x)=O(g(x)),f(x)=\Omega(g(x)),则 f(x)= \Theta (g(x)) 88 | $$ 89 | 90 | -------------------------------------------------------------------------------- /第4章 数论和密码学.md: -------------------------------------------------------------------------------- 1 | # 4.1 整除性和模算术 2 | 3 | $$ 4 | a | b,代表b能被a整除 5 | $$ 6 | 7 | 一些很简单的定理: 8 | $$ 9 | 如果a|b,a|c,则 a|(b+c)\\ 10 | 如果a|b,则当 c \in Z,a|bc \\ 11 | 如果a|b,b|c,则a|c 12 | $$ 13 | 14 | #### 模算术 15 | 16 | $$ 17 | 如果 a=dq+r,则 q=a\ \textbf{div}\ b,r=a\ \textbf{mod}\ b 18 | $$ 19 | 20 | #### 同余 21 | 22 | $$ 23 | a \equiv b (mod\ m) 代表 \\ 24 | a\ mod\ m\ = b\ mod\ m 25 | $$ 26 | 27 | 代表a和b,对于m的余数相同。 28 | $$ 29 | 如果 a \equiv b (mod\ m),则存在 k \in Z,使得 b=k \times a+m 30 | $$ 31 | 同余对于加法和乘法来说: 32 | $$ 33 | 如果:a \equiv b(mod\ m),c \equiv d(mod\ m) \\ 34 | 则:a+c \equiv b+d (mod\ m),a \times c \equiv b \times d (mod m) 35 | $$ 36 | 加法的同余很好理解: 37 | $$ 38 | b=a+{k}_{b}m,c=d+{k}_{c}m,\\ 39 | 则 b+c=a+d+({k}_{b}+{k}_{c})m 40 | $$ 41 | 乘法理解起来麻烦一点: 42 | $$ 43 | bc=(a+{k}_{b}m) \times (d+{k}_{c}m) = ac + m(a{k}_{c}+c{k}_{b}+{k}_{b}{k}_{c}m) 44 | $$ 45 | 这里千万别把a和c当作变量来理解,而是要想,它的最终结果就是一个数字,而只要是数字,后面的组合就是一个常数。 46 | 47 | 下面就是一个推论: 48 | $$ 49 | (a+b)\ \textbf{mod}\ m= ((a\ \textbf{mod}\ m) + (b\ \textbf{mod}\ m)) \textbf{mod}\ m \\ 50 | (ab)\ \textbf{mod}\ m= ((a\ \textbf{mod}\ m) \times (b\ \textbf{mod}\ m)) \textbf{mod}\ m 51 | $$ 52 | 证明: 53 | $$ 54 | a \equiv (a\ mod\ m) (mod\ m),a关于m的余数,肯定同余于其自身,例如 5\ mod\ 2=1,1\ mod\ 2=1,则 5 \equiv 1 (mod 2) \\ 55 | 同理 b \equiv (b\ mod\ m),根据上面的加法同余定理可以知道:\\ 56 | a+b \equiv (a\ mod\ m)(b\ mod\ m)(mod\ m),\\ 57 | ab \equiv (a\ mod\ m)(b\ mod\ m)(mod\ m) 58 | $$ 59 | 60 | #### 模m算术简写形式 61 | 62 | $$ 63 | a+b\ (\textbf{mod}\ m)=a {+}_{m}\ b \\ 64 | ab\ (\textbf{mod}\ m)= a {\bullet}_{m}\ b 65 | $$ 66 | 67 | 一些很容易理解的性质: 68 | 69 | 结合律: 70 | $$ 71 | (a {+}_{m}\ b){+}_{m}\ c = a {+}_{m}\ (b{+}_{m}\ c) \\ 72 | (a {\bullet}_{m}\ b) {\bullet}_{m}\ c = a {\bullet}_{m} (b\ {\bullet}_{m} c) 73 | $$ 74 | 交换律: 75 | $$ 76 | a {+}_{m} b\ = b {+}_{m}\ a \\ 77 | a {\bullet}_{m}\ b\ = b {\bullet}_{m}\ a 78 | $$ 79 | 分配率: 80 | $$ 81 | a {\bullet}_{m}\ (b {+}_{m} c)= (a {\bullet}_{m} b) {+}_{m} (a {\bullet}_{m} c) \\ 82 | (a {+}_{m} b) {\bullet}_{m} c = (a {\bullet}_{m}\ c) {+}_{m} (b {\bullet}_{m}\ c) 83 | $$ 84 | 85 | # 4.3 素数和最大公约数 86 | 87 | > 算术基本定理:每个大于1的整数都可以唯一地写为两个或多个素数的乘积。 88 | 89 | 合数,就是大于1,但是又不是素数的整数。 90 | $$ 91 | 如果n是一个合数,那么n必有一个素数因子小于等于 \sqrt{n} 92 | $$ 93 | 94 | #### 埃拉托斯特尼筛法 95 | 96 | 比如想要知道100以内有哪些数字是素数,就从最小的素数开始,凡是能被该素数整除的,均不是素数,比如从素数2开始,4,6,8,10等,直到100为止,再来是从3开始,6,9,12等,再来是从5开始,10,15,20等,直到所有7为止。至于为什么是7,因为根据上面我们可知,100肯定有一个素数小于等于10,则该值可能为2,3,5,7中的任何一个,然后在恰面的步骤中,我们除外了所有以这些为素数因子的合数,剩下的自然就是100以内的素数了。 97 | 98 | #### 梅森素数 99 | 100 | 就是形如下面的素数: 101 | $$ 102 | {2}^{p}-1,且 p 为素数 103 | $$ 104 | 与其配套的还有一个卢卡斯-莱默尔测试(Lucas-Lehmer)的测试方法,可以判定形如上面的数是否为素数。 105 | 106 | #### 最大公约数 107 | 108 | $$ 109 | d|a,且\ d|b,此时最大的 d 的值就是最大公约数,记为\ gcd(a,b) 110 | $$ 111 | 112 | 所以两个素数的最大公约数就是1。 113 | 114 | #### 最小公倍数 115 | 116 | $$ 117 | a|c,且\ b|c,此时最小的c的值就是最小公约数,记为 lcm(a,b) 118 | $$ 119 | 120 | 据说可以根据上面两个定义得出下面这个结论,但是我不知道怎么证明: 121 | 122 | $$ 123 | a,b \in {N}^{+},则 \\ 124 | ab=gcd(a,b) \cdot lcm(a,b) 125 | $$ 126 | 127 | #### 欧几里得算法:最大公约数算法 128 | 129 | $$ 130 | 如果\ a=bq+r,a,b,q,r \in N,则\ gcd(a,b)=gcd(b,r) 131 | $$ 132 | 133 | 证明: 134 | $$ 135 | 假设 d|a,d|b,则 d|r,因为 d|bq,d|a-bq,所以\ gcd(a,b)=gcd(b,r) 136 | $$ 137 | 然后在上面的基础上,不断求两个数的公约数为止,直到无法再把数据修改成上面的形式为止,比如求`gcd(287,91)` 138 | 139 | ```mathematica 140 | 287=91*3+14 141 | 91=14*6+7 142 | 14=7*2 // 没有余数了 143 | ``` 144 | 145 | 即`gcd(287,91)=7` 146 | 147 | 欧几里得算法与上面求模运算之间的关系如下: 148 | 149 | ```php 150 | function gcd(int $a,int $b){ 151 | // % 在 php 中代表求模运算,即上面的 mod 152 | $nextB=$a % $b; 153 | if (!$nextB){ 154 | return $b; 155 | } 156 | return gcd($b,$nextB); 157 | } 158 | 159 | print gcd(287,91); 160 | ``` 161 | 162 | #### 贝祖定理 163 | 164 | $$ 165 | a,b \in {N}^{+},s,t \in N,则\ \exists s \exists t\ gcd(a,b)=sa+tb 166 | $$ 167 | 168 | 这个的证明其实就是上面欧几里得算法的逆步骤: 169 | $$ 170 | 假设 d|a,d|b,且 gcd(a,b)=d,则\ a=db+r,\\ 171 | 下面开始拆分:\\ 172 | b={k}_{0}r+{n}_{0} \\ 173 | r={k}_{1}{r}_{1}+{n}_{1} \\ 174 | {r}_{1}={k}_{2}{r}_{2}+{n}_{2} \\ 175 | \cdots \\ 176 | {r}_{n}={k}_{n}{r}_{n+1} \\ 177 | 将上面的结果逆序带回去,为了便于理解,下面采用真实数据来展示 178 | $$ 179 | 首先用欧几里得算法来求`gcd(252,198)` 180 | 181 | ```mathematica 182 | 252=1*198+54 183 | 198=3*54+36 184 | 54=1*36+18 185 | 36=18*2 186 | ``` 187 | 188 | 逆着来 189 | 190 | ```mathematica 191 | 18=54-1*36 192 | // 36=198-3*54 193 | 18=54-1*(198-3*54) 194 | // 54=(252-1*198) 195 | 18=(252-1*198)-1*(198-3*(252-1*198))=4*252-5*198 196 | ``` 197 | 198 | 这里需要时候到后面的强归纳定理才能证明,这里我仅仅是想说能理解什么是贝斯定理。 199 | 200 | 这里还有一个定理: 201 | $$ 202 | m \in {N}^{+},a,b,c,d \in N,如果 ac \equiv bc (mod\ m),且 gcd(c,m)=1,则\ a \equiv b(mod\ m) 203 | $$ 204 | 这里为了证明上面的内容,需要先证明下面这个,因为下面经常要称呼到,就称为: 205 | $$ 206 | a,b,c \in {N}^{+},且\ gcd(a,b)=1,且\ a|bc,则 a|c \tag{引理2} 207 | $$ 208 | 证明: 209 | $$ 210 | 因为\ gcd(a,b)=1,所以 \exists s\exists t\ sa+tb=1,\\ 211 | 两边都 \times c \\ 212 | sac+tbc=c,因为\ a|bc,所以a|tbc,且a|sac,所以 a|(sac+tbc),所以 a|c 213 | $$ 214 | 根据上面的证明,将最开始的证明写成下面的形式: 215 | $$ 216 | 因为 ac \equiv bc\ (mod\ m),则 m|(ac-bc),则 m|(a-b)c \\ 217 | 根据上面的引理2,m|(a-b),\\ 218 | 则 a \equiv b\ (mod\ m) 219 | $$ 220 | 这里可能有人会奇怪,为什么 221 | $$ 222 | ac \equiv bc\ (mod\ m),则 m|(ac-bc) 223 | $$ 224 | 想想同余是什么意思? 225 | $$ 226 | ac={k}_{0}m+d \\ 227 | bc={k}_{1}m+d \\ 228 | ac-bd=({k}_{0}-{k}_{1})m \\ 229 | 则自然\\ 230 | m|(ac-bd) 231 | $$ 232 | 那么反过来成立吗? 233 | $$ 234 | 如果 m|(a-b),则 a \equiv b\ (mod\ m) 235 | $$ 236 | 试想一下模算术的定理: 237 | $$ 238 | a=b+{k}_{0}m \\ 239 | b=a-{k}_{0}m 240 | $$ 241 | 242 | # 4.4 求解同余方程 243 | 244 | #### 线性同余方程 245 | 246 | $$ 247 | ax \equiv b\ (mod\ m),其中,m \in {N}^{+},a,b \in N,x为变量,这样的方程称为线性同余方程 248 | $$ 249 | 250 | 首先,这是个方程,所以x是变量,剩下的就是在确定a,b,m的值之后,确定x的可选值有哪些。解体思路是这样的: 251 | 252 | 253 | 254 | -------------------------------------------------------------------------------- /辅助内容.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiddleSunshine/DiscreteMath/1cc894159d7cdecd86e2b1466d98ce0372b60d6d/辅助内容.xmind -------------------------------------------------------------------------------- /顶点之间的通路数量.md: -------------------------------------------------------------------------------- 1 | # 顶点之间的通路数量 2 | 3 | 这个证明我暂时先搁置一下,先说结论,一个图中,长度为k的回路(不是简单回路)的数量,等于该图所代表的矩阵的k次乘积后所对应位置的值。 4 | 5 | 比如下面的这张图: 6 | 7 | ![DrBXw23K5IpqUsH](https://i.loli.net/2021/02/13/DrBXw23K5IpqUsH.png) 8 | 9 | 对应的矩阵为:a,b,c,d 10 | $$ 11 | \left[ 12 | \begin{matrix} 13 | 0 & 1 & 1 & 0 \\ 14 | 1 & 0 & 0 & 1 \\ 15 | 1 & 0 & 0 & 1 \\ 16 | 0 & 1 & 1 & 0 17 | \end{matrix} 18 | \right] 19 | $$ 20 | 即: 21 | 22 | ![SFJ8zRTvM9UQkHm](https://i.loli.net/2021/02/13/SFJ8zRTvM9UQkHm.png) 23 | 24 | 然后矩阵乘以其自身8次后,结果为: 25 | $$ 26 | \left[ 27 | \begin{matrix} 28 | 8 & 0 & 0 & 8 \\ 29 | 0 & 8 & 8 & 0 \\ 30 | 0 & 8 & 8 & 0 \\ 31 | 8 & 0 & 0 & 8 32 | \end{matrix} 33 | \right] 34 | $$ 35 | 然后假设求a-d之间的回路数量,即为8: 36 | 37 | ![ATqsZ5BDbatzO2y](https://i.loli.net/2021/02/13/ATqsZ5BDbatzO2y.png) 38 | 39 | 具体的值为: 40 | 41 | - a,b,a,b,d 42 | - a,b,a,c,d 43 | - a,b,d,b,d 44 | - a,b,d,c,d 45 | - a,c,a,b,d 46 | - a,c,a,c,d 47 | - a,c,d,b,d 48 | - a,c,d,c,d 49 | 50 | [矩阵乘积的代码和原理可以见这里](https://blog.csdn.net/YQXLLWY/article/details/113797993) 51 | 52 | --------------------------------------------------------------------------------