1 排列组合

1.1 排列

\[A_n^m=n(n-1)(n-2)\cdots(n-m+1)=\frac{n!}{(n-m)!}
\]
  • 定义:从 n 个中选择 m 个组成有序数列,其中不同数列的数量。
  • 解释:从 n 个中选一个,有 n 种选法,再选第二个,从 n-1 个中选,有 n-1 种选法,以此类推,根据组合数学的乘法原理所以公式是\(n(n-1)(n-2)...(n-m+1)\)。

1.2 组合

\[C_n^m=\frac{A_n^m}{m!}=\frac{n!}{m!(n-m)!}
\]
  • 定义:从 n 个 中选择 m 个组成集合其中,不同的集合的数量。
  • 解释:在排列中去掉选择重复元素的情况就是组合了,比如 {1,2,3}、{2,3,1} 相同,所以公式是$ \frac{A_nm}{A_mm}$,即从 n 个 中选出 m 个,排列完除去 m 个全排列的数量。
  • 另外:\(C_n^m\) 还有一种写法是: \(\binom{n}{m}\),读作 n 选 m。
  • 推论:
    1. \(\binom{n}{m}+\binom{n}{m-1}=\binom{m+1}{i}\) ,(又叫帕斯卡法则),带入公式约分后易证。

二项式定理

\[(a+b)^n=\sum_{i=0}^{n}\binom{n}{i}a^{n-i}b^i
\]
  • 证明:
\[当 n=1 时,a+b= \sum_{i=0}^1\binom{1}{i}a^{1-i}b^i=\binom{1}{0}a^1b^0+\binom{1}{1}a^0b^1=a+b ,公式成立
\]
\[假设n=m 时公式成立,设n=m+1,则有:
\]
\[(a+b)^{m+1}=a(a+b)^m+b(a+b)^m
\]
\[= a\sum_{i=0}^m\binom{m}{i}a^{m-i}b^i+b\sum_{j=0}^m\binom{m}{j}a^{m-j}b^j
\]
\[= \sum_{i=0}^m\binom{m}{i}a^{m+1-i}b^i+\sum_{j=0}^m\binom{m}{j}a^{m-j}b^{j+1},提出当i=0时和当j=m时的项
\]
\[= a^{m+1}+ \sum_{i=1}^m\binom{m}{i}a^{m+1-i}b^i +b^{m+1} +\sum_{j=0}^{m-1}\binom{m}{j}a^{m-j}b^{j+1} ,令j=i-1
\]
\[= a^{m+1} +b^{m+1}+ \sum_{i=1}^m\binom{m}{i}a^{m+1-i}b^i+\sum_{i=1}^{m}\binom{m}{i-1}a^{m+1-j}b^i
\]
\[=a^{m+1} +b^{m+1}+ \sum_{i=1}^m\Bigg[\binom{m}{i}+\binom{m}{i-1}\Bigg]a^{m+1-i}b^i,根据:\binom{n}{m}+\binom{n}{m-1}=\binom{m+1}{i}
\]
\[=a^{m+1} +b^{m+1}+ \sum_{i=1}^m\binom{m+1}{i}a^{m+1-i}b^i
\]
\[= \sum_{i=0}^{m+1}\binom{m+1}{i}a^{m+1-i}b^i
\]
  • 推论:

    • $ C_n0+C_n1+C_n2\cdots+C_nn=(1+1)n=2n $
    • $ C_n0-C_n1+C_n2-C_n3\cdots +C_nn=(1-1)n=(0)^n$

Lucas 定理

若 p 是质数,则对于任意整数 $ 1 \le m \le n $ 有:

\[\binom{n}{m} \equiv \binom{n ~ mod ~ p}{m ~ mod ~ p}\binom{n/p}{m/p} (mod~p)
\]

证明较难,需要用到生成函数的知识,有兴趣的可以看看。别问我,我也不会。

使用这个公式就可以对较为麻烦的组合数进行取模。

鸽巢定理

  • 定义:将 n+1 个物体,划分为 n 组,那么有至少一组有两个(或以上)的物体。

  • 推广:将 n 个物体,划分为 k 组,那么至少存在一个分组,含有大于或等于 \(\lceil \frac{n}{k} \rceil\) 个物品。

  • 例题:给你n个正整数\(A=\{a_1,a_2...a_n\}\),和一个正整数 c,问,是否能找到一个 A 的子集 B,B 中元素的和是 c 的倍数,如果能则输出他们的编号。\(1 \le c \le n \le 10^5 ,1 \le a_i \le 10^5\)。

    • 解法:设 A 的前缀和为 $ sum_i $ ,
    \[若有 sum_l \equiv sum_r~(mod~c)
    \]
    \[即 sum_l -sum_r\equiv0 ~(mod~c)
    \]
    \[那么 \sum_{i=l+1}^ra_i\equiv0 ~(mod~c)
    \]
    \[所以\sum_{i=l+1}^ra_i 即为解
    \]
    \[前缀和的个数为 n ,模 c 的情况下去除为0的情况,总共有 c-1 种情况,n>c-1
    \]
    \[根据鸽巢定理 一定有 sum_l \equiv sum_r~(mod~c)
    \]
    \[综上所述:该题恒有解,解为\{ a_{l+1},a_{l+2},\cdots ,a_r |sum_l \equiv sum_r~(mod~c) \}
    \]

容斥定理

  • 定义:$$ 设有 n 个集合 S_i , |S_i| 表示 S_i 的大小,有:$$

    \[\left| \bigcup_{i=1}^nS_i \right|=\sum_{i=1}^{n}|S_i|-\sum_{1 \le i < j \le n}|S_i\cap S_j|+\sum_{1 \le i < j <k \le n}|S_i\cap S_j\cap S_k|- \cdots
    \]
    \[+(-1)^{m-1}\sum_{a_i<a_{i+1}}\left| \bigcap_{i=1}^mS_{a_i} \right|+ \cdots + (-1)^{n-1}\left| \bigcap_{i=1}^nS_i \right|
    \]

    公式看起来好复杂、好吓人,但实际上是个很简单的定理。

    如下图有集合A、B、C:

    显然有:

    \[|A\cup B\cup C|= |A|+|B|+|C|-|A\cap B|-|A\cap C| -|B\cap C|+|A\cap B\cap C|
    \]

    把这个问题推广到一般情况,就是我们熟知的容斥原理。

  • 证明:

    \[设~T_i~为元素~a_i~在集合~S_1,S_2,\cdots ,S_n~ 中出现的次数
    \]
    \[因为容斥定理公式相当于~1-n~的所有组合情况,也就是组合数的全集,此时我们再在全集中选择包含元素~a_i~的组合
    \]
    \[所以在容斥定理公式,中元素~a_i~出现的次数为:
    \]
    \[\sum_{j=1}^{T_i} (-1)^{i-1}\binom{T_i}{j}
    \]
    \[根据二项式定理:(1-1)^n=\sum_{i=0}^{n}\binom{n}{i}(-1)^{i} ,有:
    \]
    \[0= 1-\sum_{i=1}^{n} (-1)^{i-1}\binom{n}{i}
    \]
    \[即:\sum_{i=1}^{n} (-1)^{i-1}\binom{n}{i}=1
    \]
    \[所以 \sum_{j=1}^{T_i} (-1)^{i-1}\binom{T_i}{j} =1,即元素~a_i~出现的次数为~1
    \]
    \[也就是说在容斥定理公式任意元素出现的次数都为~1 ,那么合并起来就是并集。
    \]
  • 例题:区间互质问题,两个区间中互质对的个数,两区间范围不超过\(10^6\)。

    在考虑这个问题之前我们先考虑它的一个子问题,一个数 \(x\) 与一个区间 \([l,r]\) 的互质问题。处理这个问题,最简单的方法肯定是遍历区间然后用 \(gcd\) ,复杂度为\(O(NlogN)\),n 为区间长度,加上另外一个区间那\(O(N^2logN)\),显然太慢,这时我们可以逆向思维,转换问题,我们可以考虑求不互质的个数,然后再用全部个数减去不互质的个数。不互质也就是说,有公共的因子,如果把问题转换成求同有某个因子的数量,那就好处理,比如如果计算都有因子 2,即 2 的倍数的数量,只要讲区间数除2就好,也就是说只要 \(O(1)\) 的复杂度就可以算出区间中有某个因数的数的个数,也就是说我们可以先对数 \(x\) 进行因数分解,得到 $ m $ 个因数 $ a_1,a_2,\cdots ,a_m $,对于某个因数我们可以求出区间 \([l,r]\) 中,包含因数 $ a_i $ 的数量 $ b_i $,如有一因子为 \(a_1=3\) ,区间为 $ [5,18] $ ,那么对应的 $ b_1=\lfloor \frac{18-5+1}{3} \rfloor=5,即有{6,9,12,15,18}这 5 个数,有$ $b

    _i=\lfloor \frac{r-l+1}{a_i} \rfloor $

    看起来我们好像把所有的 $ b_i $ 加起来就可以解决这个问题了,但实际上如果直接把 $ b_i $ 加起来,最后答案会多出很多,比如同时有 2 和 3 作为因子的数,如果我们直接加,那 6 的倍数就被多算,并且如果有 2 和 6 为因子,那 6 也一定是一个因子,那就更加麻烦了。为了解决这个问题,我们还需要将问题再度分解,我们将 $ x $ 拆分成质因子 $ p_1,p_2,\cdots,p_k $,设 \(k\) 份集合\(S_1,S_2,\cdots ,S_k\) , \(S_i\) 表示在区间中包含因子 \(p_i\) 的数所构成的集合。根据容斥定理此时就有我们要求的值即:

    \[\left| \bigcup_{i=1}^kS_i \right| =\sum_{j=1}^k \left((-1)^{j-1}\sum_{a_i<a_{i+1}}\left| \bigcap_{i=1}^jS_{a_i} \right| \right)
    \]
    \[设 \sum_{a_i<a_{i+1}}\left| \bigcap_{i=1}^jS_{a_i} \right| 为 A_j
    \]
    \[有:\left| \bigcup_{i=1}^kS_i \right| =\sum_{j=1}^k (-1)^{j-1} A_j
    \]
    \[设 函数~f(x),表示~x~质因子的数量
    \]
    \[有:A_j=\sum_{f(a_i)=j} b_i
    \]

    这里的 \(A_j\) 的实际意义是区间中包含质因子大于等于 \(j\) 的数的数量,所以我们对每一个因子求出它的质因子的数对应将它的 \(b_i\) 累加到 \(A_j\) 中就可以求出 \(A_j\) 的值。换个角度说,因子是质因子的所有非空组合,我们求的 \(b_i\) 即是在这种组合下有多少区间有多少对应的数,比如将所有两两组合的因子的 \(b_i\) 值累加,那我们就可以求出区间有多少包含两个及两个以上的质因子的数的数量了,然后通过容斥定理去重,就可以得出解。

    那这个方法的复杂度如何呢?我们先观察该方法的步骤

    1. 对 \(x\) 分解质因数
    2. 对质因数进行全组合,然后计算对应的 \(b_i\) 值累加到 \(A_j\) 上。
    3. 计算容斥定理公式,得出不互质对的数量。
    4. 将区间范围减去上面求出的量,得出解。

    步骤 1 使用 Pollard-rho 算法分解质因数,复杂度为 \(O(n^{\frac{1}{4}})\),步骤 2 对质因数进行全组合,假设 \(x\) 为 $ p_1{n_1}p_2{n_2}\cdots p_n^{n_k} $ 总共有 $ (n_1+1)(n_2+1)\cdots (n_k+1) -1$ 种情况,减 1 是因为 1 虽然是因子,但是不算 ,k为质因子的种类数量,考虑到\(1081080=2×2×2×3×3×3×5×7×11×13,256\),并且计算对应的 \(b_i\) 值的复杂度为 \(O(1)\),通过查表(http://wwwhomes.uni-bielefeld.de/achim/highly.txt ),发现它的增长低于 \(O(n^{\frac{1}{4}})\) 但 $ 10^6 $ 以内大于 \(O(n^{\frac{1}{4}})\),在。步骤 3 计算交错加减,复杂度 $ O(k) $ 。步骤 4 复杂度 \(O(1)\)。综上所述,在数据范围为 $ 10^6 $ 时,最坏的情况需要百位的运算次数,在普适的范围内复杂度可以看作\(O(n^{\frac{1}{4}})\)。

    我们在\(O(n^{\frac{1}{4}})\)的复杂度内求出了一个数对于一个区间的互质对,那一个区间和一个区间的互质对一样,对区间中每一个数求解就好,复杂度为\(O(n^{\frac{5}{4}})\)。

另外

组合数还有很多内容比如:

  • 卡特兰数
  • 斯特林数
  • 贝尔数
  • 伯努利数
  • 多重集的排列组合
  • 不相邻排列
  • 错位排列
  • 圆排列

这些都是一些经典计数模型,可以不用会证明或者推导,但是要知道他们能解决什么类型的问题,他们的模型是什么。

如果对组合计数很感兴趣,可以学下生成函数(母函数)

ACM组合计数入门的更多相关文章

  1. HDU4609 FFT+组合计数

    HDU4609 FFT+组合计数 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4609 题意: 找出n根木棍中取出三根木棍可以组成三角形的概率 题解: ...

  2. bzoj 2281 [Sdoi2011]黑白棋(博弈+组合计数)

    黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色 ...

  3. BZOJ 4555: [Tjoi2016&Heoi2016]求和 [分治FFT 组合计数 | 多项式求逆]

    4555: [Tjoi2016&Heoi2016]求和 题意:求\[ \sum_{i=0}^n \sum_{j=0}^i S(i,j)\cdot 2^j\cdot j! \\ S是第二类斯特林 ...

  4. BZOJ 4555: [Tjoi2016&Heoi2016]求和 [FFT 组合计数 容斥原理]

    4555: [Tjoi2016&Heoi2016]求和 题意:求\[ \sum_{i=0}^n \sum_{j=0}^i S(i,j)\cdot 2^j\cdot j! \\ S是第二类斯特林 ...

  5. 【BZOJ5491】[HNOI2019]多边形(模拟,组合计数)

    [HNOI2019]多边形(模拟,组合计数) 题面 洛谷 题解 突然特别想骂人,本来我考场现切了的,结果WA了几个点,刚刚拿代码一看有个地方忘记取模了. 首先发现终止态一定是所有点都向\(n\)连边( ...

  6. [总结]数论和组合计数类数学相关(定理&证明&板子)

    0 写在前面 0.0 前言 由于我太菜了,导致一些东西一学就忘,特开此文来记录下最让我头痛的数学相关问题. 一些引用的文字都注释了原文链接,若侵犯了您的权益,敬请告知:若文章中出现错误,也烦请告知. ...

  7. 【BZOJ5323】[JXOI2018]游戏(组合计数,线性筛)

    [BZOJ5323][JXOI2018]游戏(组合计数,线性筛) 题面 BZOJ 洛谷 题解 显然要考虑的位置只有那些在\([l,r]\)中不存在任意一个约数的数. 假设这样的数有\(x\)个,那么剩 ...

  8. 【BZOJ5305】[HAOI2018]苹果树(组合计数)

    [BZOJ5305][HAOI2018]苹果树(组合计数) 题面 BZOJ 洛谷 题解 考虑对于每条边计算贡献.每条边的贡献是\(size*(n-size)\). 对于某个点\(u\),如果它有一棵大 ...

  9. 【BZOJ3142】[HNOI2013]数列(组合计数)

    [BZOJ3142][HNOI2013]数列(组合计数) 题面 BZOJ 洛谷 题解 唯一考虑的就是把一段值给分配给\(k-1\)天,假设这\(k-1\)天分配好了,第\(i\)天是\(a_i\),假 ...

随机推荐

  1. k8s入门之集群搭建(二)

    一.准备三台节点 从上篇文章 k8s入门之基础环境准备(一)安装的Ubuntu虚拟机克隆出三台虚拟机,如图所示 启动这三台虚拟机节点,分别做如下配置 虚拟机名称 IP HostName k8sMast ...

  2. Python GDAL矢量转栅格详解

    前言:挺久没有更新博客了,前段时间课程实验中需要用代码将矢量数据转成栅格,常见的点栅格化方法通过计算将点坐标(X,Y)转换到格网坐标(I,J),线栅格化方法主要有DDA算法.Bresenham算法等, ...

  3. Golang Zap日志

    Zap日志解析 Config.yaml zap: level: 'info' #日志级别 format: 'console' #输出的级别,有console和json prefix: '[cateri ...

  4. DFA算法之内容敏感词过滤

    DFA 算法是通过提前构造出一个 树状查找结构,之后根据输入在该树状结构中就可以进行非常高效的查找. 设我们有一个敏感词库,词酷中的词汇为:我爱你我爱他我爱她我爱你呀我爱他呀我爱她呀我爱她啊 那么就可 ...

  5. prometheus监控预警之AlertManager邮箱报警

    Alertmanager 主要用于接收 Prometheus 发送的告警信息,它支持丰富的告警通知渠道,例如邮件.微信.钉钉.Slack 等常用沟通工具,而且很容易做到告警信息进行去重,降噪,分组等, ...

  6. Java 线程安全 与 锁

    Java 线程安全 与 锁 多线程内存模型 线程私有栈内存 每个线程 私有的内存区域 进程公有堆内存 同一个进程 共有的内存区域 为什么会有线程安全问题? 多个线程同时具有对同一资源的操作权限,又发生 ...

  7. 面试官:RocketMQ是什么,它有什么特性与使用场景?

    哈喽!大家好,我是小奇,一位热爱分享的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 作为一名Java程序员,Roc ...

  8. C Primer Plus 学习笔记 -- 前六章

    记录自己学习C Primer Plus的学习笔记 第一章 C语言高效在于C语言通常是汇编语言才具有的微调控能力设计的一系列内部指令 C不是面向对象编程 编译器把源代码转化成中间代码,链接器把中间代码和 ...

  9. 用Docker打包Python运行环境

    虽然Docker作为部署环境打包镜像的工具,和我的科研并没有直接的关系.但我觉得在项目中运用Docker来打包环境依赖也可以大大提高工作效率,于是准备专门学习一下Docker. 1. Docker基础 ...

  10. 【FineBI】增量数据更新语句

    SELECT * FROM t_abike_user WHERE AddUserTime BETWEEN '2016-11-17 10:49:04' AND '2021-07-31 23:59:59'