嘘~ 正在从服务器偷取页面 . . .

OI数学总结-组合数学


OI数学总结-组合数学

施工中,咕咕咕….

排列组合

更多详见 小蓝书 16.1

下面两个指的是无重复的排列与组合

排列数

从 $n$ 个不同元素中取 $k(k\le n)$ 个不同元素,并按一定顺序排成一列的方案数

也可写作 $\mathrm{P}_{n}^{k}$ 或直接用组合数写法 $k! \times \binom{n}{k}$

代码求解

$O(n)$ 计算

例如求解 $A_{n-m+1}^{m} \bmod p$

int res=1;
for(int i=n-m+1; i>=n-2*m+2; i--)
    res=res*i%p;
cout << res << '\n'

组合数

从 $n$ 个不同元素中取 $k(k \le n)$ 个不同元素的方案数

高中一般记作 $\mathrm{C}_n^{k}$ ,不是很推荐使用。

特别地,规定当 $k > n$ 时, $\mathrm{A}_n^{k} = \mathrm{C}_n^{k}=0$

代码求解

$O(n^2)$ 递推
for(int i=0; i<=1000; i++)
{
    C[i][0]=1;
    for(int j=1; j<=i; j++)
        C[i][j]=(C[i-1][j]+C[i-1][j-1])%p;
}
$O(p)$ Lucas定理

详见 [OI数学总结-数论]

P3807 【模板】卢卡斯定理/Lucas 定理

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iomanip>
#include <random>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define N (int)(2e5+15)
int Q,n,m,p;
int fac[N];
int qpow(int a,int b,int p)
{
	int ans=1,base=a;
	while(b)
	{
		if(b&1)ans=ans*base%p;
		base=base*base%p;
		b>>=1;
	}
	return ans;
}
// n 选 m
int C(int n,int m,int p)
{
	if(n<m)return 0;
	return fac[n]*qpow(fac[m],p-2,p)%p*qpow(fac[n-m],p-2,p)%p;
}
int lucas(int n,int m,int p)
{
	if(!m)return 1;
	return lucas(n/p,m/p,p)*C(n%p,m%p,p)%p;
}
signed main()
{
	cin >> Q;
	while(Q--)
	{
		cin >> n >> m >> p;
		fac[1]=fac[0]=1;
		for(int i=2; i<=n+m; i++)
			fac[i]=fac[i-1]*i%p;
		cout << lucas(n+m,m,p) << '\n'; // C(n+m,n)
	}
	return 0;
}

排列组合常用公式

这个可以单独拉出来讲,到时候写一个。

$(2)$ 可以通过杨辉三角(数学归纳法)简单证明。

证明的话直接移项,然后一直根据递推式合并即可。


容斥原理

容斥原理(principle of inclusion-exclusion):令 $X$ 为一个有限集合,$P_1, P_2,\dots , P_m$ 是一些性质的集合,对于任意 $S \subseteq [m]$ ,即 $S\subseteq \{1,2,\cdots,m\}$ ,定义 $N(S) = \{x \in X \mid \forall i \in S : x \text{ has } P_i\}$ 。那么 $X$ 中满足性质 $P_{1\sim m}$ 的元素个数

如果是不满足任何一个性质的话,把指数中的 $|S|+1$ 改成 $|S|$ 即可。


特别地,对于任意的 $S \subseteq [m]$ ,如果 $N(S)$ 只和 $S$ 的大小(即 $|S|$ )有关,那么式子可以化简为

其中 $N(i)$ 表示对于任意满足 $S \subseteq [m],|S|=i$ 的 $N(S)$ 值。

如果是不满足任何一个性质的话,把指数中的 $i+1$ 改成 $i$ 即可。

容斥原理的常用技巧

  1. 定义一些“坏性质” $P_1,\dots,P_m$

  2. 找到对于每个 $S\subseteq [m]$ 计算 $N(S)$ 的方法

  3. 套用容斥原理计算不满足任何一个“坏性质”的元素个数

  4. 注意这里求的是不满足任何坏性质,因此用以下公式


鸽巢原理(抽屉原理)

假如有 $n+1$个元素放到 $n$ 个集合中去,其中必定有一个集合里至少有两个元素。

应用

  1. 任意 $n+1$ 个数中至少有 $2$ 个数与 $n$ 同余

第二类斯特林数

第二类斯特林数记作 $S(n,k)$ 或 $\left\{\begin{array}{l}n \\k\end{array}\right\}$ 。

表示将 $n$ 个两两不同的元素划分为 $k$ 个无区别的非空子集的方案数。

换个说法,$n$ 个不同的球放到 $m$ 个相同的盒子,不可以有空盒子的方案数。

注意,如果是 $n$ 个相同的球,那就是插板法的问题了,所以不同的球是第二类斯特林数的关键。

边界:

递推式:

鉴于我每次都记错这个递推式,我要着重讲一下它的含义。

$\left\{\begin{array}{l}n-1 \\k-1\end{array}\right\}$ 表示把第 $n$ 个球单独放在新的第 $k$ 个盒子里。

$k\left\{\begin{array}{c}n-1\\k\end{array}\right\}$ 表示把第 $n$ 个球放在任意盒子里,并且此时盒子数量仍然是 $k$ 。

可能写的有点奇怪,但是熟悉递推的同学应该知道我在说什么吧。


第一类斯特林数

第一类斯特林数记作 $s(n,k)$ 或 $\left[\begin{array}{l}n \\k\end{array}\right]$ 。

表示将 $n$ 个两两不同的元素划分为 $k$ 个互不区分的非空轮换的方案数。

换个说法,$n$ 个不同的数恰好划分为 $k$ 个圆排列的方案数

边界:

递推式:


伯努利数

常用于等幂求和( $m$ 次幂和的公式)

记 $S_m(n) = \sum\limits_{i=0}^{n-1} i^m$ ,则

其中 $B_k$ 为伯努利数,定义如下

例如 $\binom{2}{0} B_0 = \binom{2}{1}B_1 = 0$

$n$ 0 1 2 3 4 5 6 7 $\dots$
$B_n$ $1$ $-\frac{1}{2}$ $\frac{1}{6}$ $0$ $-\frac{1}{30}$ $0$ $\frac{1}{42}$ $0$ $\dots$

代码求解

咕咕咕…


贝尔数(Bell数)

$B_n$ 是基数为 $n$ 的集合的划分方法的数目

集合 $S$ 的一个划分定义为 $S$ 的两两不相交的非空子集的族,它们的并为 $S$

例如 $B_3=5$ ,因为 $3$ 个元素的集合 $a,b,c$ 有 $5$ 种不同的划分方法

贝尔数适合递推公式

贝尔三角形(类似于杨辉三角)

则有 $B_n = A_{n,1}$

代码求解

咕咕咕….


文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录