从 n n n 个不同的物品中不重复地取出 r r r 个,排列数 P n r = n ! / ( n − r ) ! P_n^r = n!/(n-r)! P n r = n ! / ( n − r )!
从 n n n 个不同的物品中可重复地取出 r r r 个,排列数为 n r n^r n r
圆排列的排列数:从 n n n 个元素中选 r r r 个的圆排列的排列数为 P n r r = n ! r ( n − r ) ! \frac{P_n^r}{r}=\frac{n!}{r(n-r)!} r P n r = r ( n − r )! n !
S S S 是一个多重集,有 k k k 个不同的元素,每个元素都有无穷重复个数,那么 S S S 的 r r r 排列个数为 k r k^r k r
S S S 是一个多重集,有 k k k 个不同的元素,每个元素的重数分别为 n 1 , ⋯ , n k n_1,\cdots,n_k n 1 , ⋯ , n k ,n = n 1 + n 2 + ⋯ + n k n=n_1+n_2+\cdots+n_k n = n 1 + n 2 + ⋯ + n k ,则 S S S 的 n n n 排列的个数为 n ! n 1 ! n 2 ! ⋯ n k ! \frac{n!}{n_1!n_2! \cdots n_k!} n 1 ! n 2 ! ⋯ n k ! n !
从 n n n 个不同物品中选 r r r 个元素的组合为 C n r C_n^r C n r
S S S 是一个多重集,有 k k k 个不同的元素,每个元素都有无穷个,S S S 的 r r r 组合的个数为 C r + k − 1 k − 1 C_{r+k-1}^{k-1} C r + k − 1 k − 1 可以不定方程隔板法证明
求组合数#
利用公式 C a b = C a − 1 b + C a − 1 b − 1 C_a^b = C_{a-1}^b + C_{a - 1}^{b-1} C a b = C a − 1 b + C a − 1 b − 1
数据范围 a , b ≤ 2000 a,b \le 2000 a , b ≤ 2000 左右
代码如下
for ( int i = 0 ; i < N; i ++ )
for ( int j = 0 ; j <= i; j ++ ) {
else C[i][j] = (C[i - 1 ][j] + C[i - 1 ][j - 1 ]) % MOD;
利用公式 C a b = a ! b ! ( a − b ) ! C_a^b = \frac{a!}{b!(a-b)!} C a b = b ! ( a − b )! a ! ,因此可以预处理阶乘和取除法的模所需逆元
数据范围大概在 10 5 10^5 1 0 5 左右
注意 :模数得是素数
代码如下:
使用:C_a^b = fact[a] * inv[b] * inv[a - b]
int kpow ( int a , int k , int m ) {
if (k & 1 ) res = 1 ll * res * a % m;
for ( int i = 1 ; i < N; i ++ )
fact[i] = 1 ll * fact[i - 1 ] * i % MOD, inv[i] = kpow (fact[i], MOD - 2 , MOD);
Lucas 定理,p p p 为素数,使用限制 a ≥ p a \ge p a ≥ p
时间复杂度 O ( n ) O(n) O ( n )
C a b ≡ C a m o d p b m o d p ∗ C a / p b / p ( m o d p ) C_a^b \equiv C_{a \ mod \ p} ^ {b \ mod \ p} * C_{a / p} ^ {b / p} (mod \ p) C a b ≡ C a m o d p b m o d p ∗ C a / p b / p ( m o d p ) 可以证明:
先将 a, b 分别写成 p 进制
a = a 0 + a 1 p + a 2 p 2 + ⋯ + a k p k a = a_0 + a_1p + a_2p^2 + \cdots + a_kp^k a = a 0 + a 1 p + a 2 p 2 + ⋯ + a k p k b = b 0 + b 1 p + b 2 p 2 + ⋯ + b k p k b = b_0 + b_1p + b_2p^2 + \cdots + b_kp^k b = b 0 + b 1 p + b 2 p 2 + ⋯ + b k p k 由于 ( 1 + x ) p = 1 + C p 1 x + C p 2 x 2 + ⋯ + C p p x p (1+x)^p=1 + C_p^1x + C_p^2x^2 + \cdots + C_p^px^p ( 1 + x ) p = 1 + C p 1 x + C p 2 x 2 + ⋯ + C p p x p ,而 p 又是质数,因此 ( 1 + x ) p ≡ 1 + x p ( m o d p ) (1+x)^p \equiv 1 + x^p (mod \ p) ( 1 + x ) p ≡ 1 + x p ( m o d p )
同理,也可知 ( 1 + x ) p k ≡ 1 + x p k ( m o d p ) (1+x)^{p^k} \equiv 1 + x^{p^k} (mod \ p) ( 1 + x ) p k ≡ 1 + x p k ( m o d p ) ,其中 k ≥ 1 k \ge 1 k ≥ 1
可以利用生成函数证明,由于
( 1 + x ) a = ( 1 + x ) a 0 + a 1 p + a 2 p 2 + ⋯ + a k p k = ( 1 + x ) a 0 ( ( 1 + x ) p ) a 1 ⋯ ( ( 1 + x ) p k ) a k (1 + x)^a = (1+x)^{a_0 + a_1p + a_2p^2 + \cdots + a_kp^k} = (1 + x)^{a_0}((1+x)^p)^{a_1} \cdots ((1+x)^{p^k})^{a_k} ( 1 + x ) a = ( 1 + x ) a 0 + a 1 p + a 2 p 2 + ⋯ + a k p k = ( 1 + x ) a 0 (( 1 + x ) p ) a 1 ⋯ (( 1 + x ) p k ) a k 故
( 1 + x ) a ≡ ( 1 + x ) a 0 ( 1 + x p ) a 1 ⋯ ( 1 + x p k ) a k ( m o d p ) (1 + x)^a \equiv (1+x)^{a_0}(1+x^p)^{a_1}\cdots (1+x^{p^k})^{a_k} (mod \ p) ( 1 + x ) a ≡ ( 1 + x ) a 0 ( 1 + x p ) a 1 ⋯ ( 1 + x p k ) a k ( m o d p ) 左边关于 x b x^b x b 的系数为 C a b C_a^b C a b ,右边关于 x b x_b x b 即 x b 0 + b 1 p + b 2 p 2 + ⋯ + b k p k x^{b_0 + b_1p + b_2p^2 + \cdots + b_kp^k} x b 0 + b 1 p + b 2 p 2 + ⋯ + b k p k 为
C a 0 b 0 C a 1 b 1 ⋯ C a k b k C_{a_0}^{b_0}C_{a_1}^{b_1}\cdots C_{a_k}^{b_k} C a 0 b 0 C a 1 b 1 ⋯ C a k b k 由于 b m o d p = b 0 , a m o d p = a 0 b \ mod \ p = b_0, a \ mod \ p = a_0 b m o d p = b 0 , a m o d p = a 0 ,故 C a 0 b 0 = C a m o d p b m o d p C_{a_0}^{b_0} = C_{a \ mod \ p} ^ {b \ mod \ p} C a 0 b 0 = C a m o d p b m o d p
又 a / p = a 1 + a 2 p 1 + ⋯ + a k p k − 1 a / p = a_1 + a_2p^1 + \cdots + a_kp^{k-1} a / p = a 1 + a 2 p 1 + ⋯ + a k p k − 1 ,b / p = b 1 + b 2 p 1 + ⋯ + b k p k − 1 b / p = b_1 + b_2p^1 + \cdots + b_kp^{k-1} b / p = b 1 + b 2 p 1 + ⋯ + b k p k − 1
由上述求解 C a b C_a^b C a b 的过程同理可得 C a / p b / p = C a 1 b 1 ⋯ C a k b k C_{a / p}^{b / p} = C_{a_1}^{b_1}\cdots C_{a_k}^{b_k} C a / p b / p = C a 1 b 1 ⋯ C a k b k
因此原命题得证
计算利用lucas计算组合数步骤:(1)线性筛;(2)lucas递归计算;(3)利用质因数的指数求C a b C_a^b C a b ,其中 a , b < p a,b<p a , b < p ,特判 a < b a<b a < b 时组合数为 0,求质因数的指数使用阶乘的质因数分解
高精度算 C a b C_a^b C a b ,所需知识点:[[数论&线性代数#阶乘质因数分解]] ;然后利用高精度算乘法
时间复杂度 n ≤ 30000 n \le 30000 n ≤ 30000 ,差不多是比较极限
代码如下:
for ( int i = 2 ; i <= n; i ++ ) {
if ( ! st[i]) p[cnt ++ ] = i;
for ( int j = 0 ; i <= n / p[j]; j ++ ) {
if (i % p[j] == 0 ) break ;
void divide ( int n , int type ) {
for ( int i = 0 ; p[i] <= n; i ++ ) {
for ( int j = n / p[i]; j; j /= p[i]) sum += j;
vector < int > mul ( vector < int > & a , int b ) {
for ( int i = 0 , t = 0 ; t || i < a. size (); i ++ ) {
if (i < a. size ()) t += b * a[i];
组合计数#
递推法,也就是dp状态设计
隔板法
经典应用 x 1 + x 2 + ⋯ + x k = n x_1+x_2+\cdots+x_k = n x 1 + x 2 + ⋯ + x k = n 有多少组正整数解,其中的等式可以变成不等式,然后如果 x i ≥ 0 x_i \ge 0 x i ≥ 0 ,则可以利用 y i = x i + 1 , ∑ y i = n + k y_i=x_i+1,\sum{y_i}=n+k y i = x i + 1 , ∑ y i = n + k 的映射来计算
抽屉法
通常和整数求余进行结合,把余数用抽屉来处理
特殊数列,卡特兰数
容斥原理# 容斥原理计算公式:
集合 S S S 中不具有性质 P 1 , P 2 , ⋯ , P n P_1,P_2,\cdots,P_n P 1 , P 2 , ⋯ , P n 的对象个数为
∣ A 1 ‾ ∩ A 2 ‾ ∩ ⋯ ∩ A n ‾ ∣ = ∣ S ∣ − ∑ ∣ A i ‾ ∣ + ∑ ∣ A i ‾ ∩ A j ‾ ∣ + ⋯ + ( − 1 ) n ∣ A 1 ‾ ∩ ⋯ A n ‾ ∣ |\overline{A_1} \cap \overline{A_2} \cap \cdots \cap \overline{A_n}|=|S|-\sum|\overline{A_i}| + \sum|\overline{A_i}\cap \overline{A_j}| + \cdots + (-1)^n|\overline{A_1}\cap \cdots \overline{A_n}| ∣ A 1 ∩ A 2 ∩ ⋯ ∩ A n ∣ = ∣ S ∣ − ∑ ∣ A i ∣ + ∑ ∣ A i ∩ A j ∣ + ⋯ + ( − 1 ) n ∣ A 1 ∩ ⋯ A n ∣
集合 S S S 中至少具有性质 P 1 , P 2 , ⋯ , P n P_1,P_2,\cdots,P_n P 1 , P 2 , ⋯ , P n 之一的对象个数为
∣ A 1 ∪ A 2 ∪ ⋯ ∪ A n ∣ = ∑ ∣ A i ∣ − ∑ ∣ A i ∩ A j ∣ + ⋯ ( − 1 ) n + 1 ∣ A 1 ∩ A 2 ∩ ⋯ A n ∣ |A_1\cup A_2 \cup \cdots \cup A_n| = \sum|A_i| - \sum|A_i \cap A_j| + \cdots (-1)^{n+1}|A_1\cap A_2 \cap \cdots A_n| ∣ A 1 ∪ A 2 ∪ ⋯ ∪ A n ∣ = ∑ ∣ A i ∣ − ∑ ∣ A i ∩ A j ∣ + ⋯ ( − 1 ) n + 1 ∣ A 1 ∩ A 2 ∩ ⋯ A n ∣
卡特兰数 Catalan 数# Catalan 数是一个数列,定义为 C n = 1 n + 1 C 2 n n C_n = \frac{1}{n+1}C_{2n}^n C n = n + 1 1 C 2 n n
卡特兰数:1 , 1 , 2 , 5 , 14 , 42 , 132 , 429 , 1430 , 4862 , 16796 1,1,2,5,14,42,132,429,1430,4862,16796 1 , 1 , 2 , 5 , 14 , 42 , 132 , 429 , 1430 , 4862 , 16796
计算公式
C n = 1 n + 1 C 2 n n = C 2 n n − C 2 n n + 1 C_n=\frac{1}{n+1}C_{2n}^n = C_{2n}^n - C_{2n}^{n+1} C n = n + 1 1 C 2 n n = C 2 n n − C 2 n n + 1
该计算公式从一个基本模型中推导:把 n n n 个 1 1 1 和 n n n 个 0 0 0 排成一行,使得这一行的任意前 k k k 个数中的 1 1 1 的数量总是大于等于 0 0 0 的数量
递推 C n = C 0 C n − 1 + C 1 C n − 2 + ⋯ + C n − 1 C 0 C_n=C_0C_{n-1}+C_1C_{n-2}+\cdots+C_{n-1}C_0 C n = C 0 C n − 1 + C 1 C n − 2 + ⋯ + C n − 1 C 0 ,C 0 = 1 C_0=1 C 0 = 1
C n = 4 n − 2 n + 1 C n − 1 , C 0 = 1 C_n = \frac{4n-2}{n+1}C_{n-1}, C_0=1 C n = n + 1 4 n − 2 C n − 1 , C 0 = 1
当 n ≤ 500 n\le 500 n ≤ 500 时,可以使用公式 2 2 2 ,比较大就需要 1 , 3 1,3 1 , 3 公式
棋盘问题
括号问题
出栈序列问题
二叉树问题
三角剖分问题
有 n + 1 n+1 n + 1 条边的凸多边形区域,在内部插入不相交的对角线,把凸多边形划分为多个三角形
二叉树问题#
n n n 个点形成的所有二叉树共有多少叶子数量?
解答:对于每棵有 n n n 结点,有 g ( n ) g(n) g ( n ) 个叶子的二叉树,将其叶子删掉,将会得到 g ( n ) g(n) g ( n ) 个 n − 1 n-1 n − 1 结点的二叉树。而一个 n − 1 n - 1 n − 1 结点的二叉树有 n n n 个位置可以插入叶子,因此每棵 n − 1 n-1 n − 1 结点的树被得到了 n n n 次,因此 f ( n − 1 ) n = g ( n ) = C 2 n − 2 n − 1 f(n-1)n=g(n) = C_{2n-2}^{n-1} f ( n − 1 ) n = g ( n ) = C 2 n − 2 n − 1
博弈论# Nim 游戏# Nim 游戏:当一堆石子的数量异或值为 0 时,则为必败态,也即异或值不为 0 时,为必胜态
证明:前置:必胜态转移的必败态只需要某种取法能转移到必败态即可,而必胜态转移到必败态需要无论此时如何操作,下一步转移一定是必败态
1、首先证明,必胜态一定存在一种方式能转移为必败态
设一堆石子的数量为 a 1 , a 2 , ⋯ , a n a_1, a_2, \cdots, a_n a 1 , a 2 , ⋯ , a n ,由必胜态可知, a 1 ⊕ a 2 ⊕ ⋯ ⊕ a n = k ≠ 0 a_1 \oplus a_2 \oplus \cdots \oplus a_n = k \neq 0 a 1 ⊕ a 2 ⊕ ⋯ ⊕ a n = k = 0 , 因此k k k 一定有高位 1 在第 b i t bit bi t 位,那么一定存在 a i a_i a i 的 b i t bit bi t 位为 1。可以证明,若 {a i a_i a i } 中不存在 b i t bit bi t 为 1,那么这些数异或的值 k k k 的 b i t bit bi t 位也一定不为 1,矛盾。
因此,我们可以将 a i ′ = a i ⊕ k a_i^{\prime} = a_i \oplus k a i ′ = a i ⊕ k ,由于 k k k 的 b i t bit bi t 位以上的位数为 0 0 0 ,因此,a i ′ < a i a_i^\prime < a_i a i ′ < a i ,即在第 i i i 堆取走 a i − a i ′ a_i - a_i^\prime a i − a i ′ 个石子,那么此时所有石子数量异或值为 a 1 ⊕ a 2 ⊕ ⋯ a i ′ ⋯ ⊕ a n = a 1 ⊕ a 2 ⊕ ⋯ a i ⊕ k ⋯ ⊕ a n = k ⊕ k = 0 a_1 \oplus a_2 \oplus \cdots a_i^{\prime} \cdots \oplus a_n = a_1 \oplus a_2 \oplus \cdots a_i\oplus k \cdots \oplus a_n = k \oplus k = 0 a 1 ⊕ a 2 ⊕ ⋯ a i ′ ⋯ ⊕ a n = a 1 ⊕ a 2 ⊕ ⋯ a i ⊕ k ⋯ ⊕ a n = k ⊕ k = 0 ,这样就由必胜态转移为必败态
2、然后证明,必败态无论如何操作都会转移为必胜态,即证,无论从哪堆石子拿石子,一定会使得其异或值不为 0
反证法:假设在 a i a_i a i 中拿 a i − a i ′ > 0 a_i - a_i^{\prime} \gt 0 a i − a i ′ > 0 个石子,有 a 1 ⊕ a 2 ⊕ ⋯ a i ′ ⋯ ⊕ a n = k ′ = 0 a_1 \oplus a_2 \oplus \cdots a_i^{\prime} \cdots \oplus a_n = k^{\prime} = 0 a 1 ⊕ a 2 ⊕ ⋯ a i ′ ⋯ ⊕ a n = k ′ = 0 那么 k ⊕ k ′ = a i ⊕ a i ′ = 0 k \oplus k^{\prime} = a_i \oplus a_i^{\prime} = 0 k ⊕ k ′ = a i ⊕ a i ′ = 0 ,也就是说 a i = a i ′ a_i = a_i^{\prime} a i = a i ′ ,这与假设不符,因此这样就相当于没有拿石子,矛盾。
证毕
公平组合游戏# 若一个游戏满足:
由两名玩家交替行动;
在游戏进程的任意时刻,可以执行的合法行动与轮到哪名玩家无关;
不能行动的玩家判负;
则称该游戏为一个公平组合游戏。
NIM博弈属于公平组合游戏,但城建的棋类游戏,比如围棋,就不是公平组合游戏。因为围棋交战双方分别只能落黑子和白子,胜负判定也比较复杂,不满足条件2和条件3。
有向图游戏# 给定一个有向无环图,图中有一个唯一的起点,在起点上放有一枚棋子。两名玩家交替地把这枚棋子沿有向边进行移动,每次可以移动一步,无法移动者判负。该游戏被称为有向图游戏。
任何一个公平组合游戏都可以转化为有向图游戏 。具体方法是,把每个局面看成图中的一个节点,并且从每个局面向沿着合法行动能够到达的下一个局面连有向边。
Mex 运算# 设S表示一个非负整数集合。定义m e x ( S ) mex(S) m e x ( S ) 为求出不属于集合S的最小非负整数的运算,即:
m e x ( S ) = m i n { x } mex(S) = min\{x\} m e x ( S ) = min { x } , x x x 属于自然数,且x x x 不属于S S S
比如:m e x ( { 0 , 1 , 2 , 4 , 5 } ) = 3 , m e x ( { 1 , 4 , 5 , 6 } ) = 0 mex(\{0,1,2,4,5\})=3, mex(\{1,4,5,6\})=0 m e x ({ 0 , 1 , 2 , 4 , 5 }) = 3 , m e x ({ 1 , 4 , 5 , 6 }) = 0
SG 函数# 在有向图游戏中,对于每个节点x x x ,设从x x x 出发共有k k k 条有向边,分别到达节点y 1 , y 2 , … , y k y_1, y_2, …, y_k y 1 , y 2 , … , y k ,定义S G ( x ) SG(x) SG ( x ) 为x x x 的后继节点y 1 , y 2 , … , y k y_1, y_2, …, y_k y 1 , y 2 , … , y k 的S G SG SG 函数值构成的集合再执行m e x ( S ) mex(S) m e x ( S ) 运算的结果,即:
S G ( x ) = m e x ( S G ( y 1 ) , S G ( y 2 ) , … , S G ( y k ) ) SG(x) = mex({SG(y_1), SG(y_2), …, SG(y_k)}) SG ( x ) = m e x ( SG ( y 1 ) , SG ( y 2 ) , … , SG ( y k ) )
特别地,整个有向图游戏G G G 的S G SG SG 函数值被定义为有向图游戏起点s s s 的S G SG SG 函数值,即S G ( G ) = S G ( s ) SG(G) = SG(s) SG ( G ) = SG ( s ) 。
有向图游戏的和# 设G 1 , G 2 , … , G m G_1, G_2, …, G_m G 1 , G 2 , … , G m 是m m m 个有向图游戏。定义有向图游戏G G G ,它的行动规则是任选某个有向图游戏G i Gi G i ,并在G i Gi G i 上行动一步。G G G 被称为有向图游戏G 1 , G 2 , … , G m G_1, G_2, …, G_m G 1 , G 2 , … , G m 的和。
有向图游戏的和的S G SG SG 函数值等于它包含的各个子游戏S G SG SG 函数值的异或和,即:
S G ( G ) = S G ( G 1 ) ⊕ S G ( G 2 ) ⊕ … ⊕ S G ( G m ) SG(G) = SG(G_1) \oplus SG(G_2) \oplus … \oplus SG(G_m) SG ( G ) = SG ( G 1 ) ⊕ SG ( G 2 ) ⊕ … ⊕ SG ( G m )
有向图游戏的某个局面必胜,当且仅当该局面对应结点的S G SG SG 函数值大于0
有向图游戏的某个局面必败,当且仅当该局面对应结点的S G SG SG 函数值等于0