排列组合与母函数

排列组合

排列就是指从给定个数的元素中取出指定个数的元素进行排序;组合是指从给定个数的元素中仅仅取出指定个数的元素,不考虑排序

加法&乘法原理

加法原理:完成一个事情有n类方法, a i a_i ai表示第 i i i类方法的数目。那么完成这件事共有 S = a 1 + a 2 + ⋯ + a n S=a_1+a_2+\dots+a_n S=a1+a2++an种不同的方法

乘法原理:完成一个事情有n个步骤, a i a_i ai表示第 i i i个方法数目。那么完成这件事共有 S = a 1 × a 2 × ⋯ × a n S=a_1\times a_2\times\dots\times a_n S=a1×a2××an种方法

排列与组合基础

排列数

n n n个不同元素中,任取 m ( m ≤ n ) m(m\le n) m(mn)个元素按照一定的顺序排成一列,叫做从 n n n个不同元素中取出 m m m个元素的一个排列,用符号 A n m A_n^m Anm或者 P n m P_n^m Pnm表示。

计算公式 A n m = n ( n − 1 ) ( n − 2 ) … ( n − m + 1 ) = n ! ( n − m ) ! A_n^m=n(n-1)(n-2)\dots(n-m+1)=\frac{n!}{(n-m)!} Anm=n(n1)(n2)(nm+1)=(nm)!n!

公式的理解: n n n个人选 m m m个人来排队,第一个有 n n n个选择,第二个有 n − 1 n-1 n1个选择,则最后一个有 n − m + 1 n-m+1 nm+1个选择

组合数

n n n个不同元素中,任取 m m m个元素组成一个集合,叫做从 n n n个不同元素中取出 m m m个元素的一个组合,用符号 C n m C_n^m Cnm来表示

计算公式 C n m = A n m m ! = n ! m ! ( n − m ) ! C_n^m=\frac{A_n^m}{m!}=\frac{n!}{m!(n-m)!} Cnm=m!Anm=m!(nm)!n!

公式的理解:考虑从 n n n个人选 m m m个出来,不排序和在乎顺序是 C n m C_n^m Cnm;在乎排序就是 A n m A_n^m Anm,去掉重复就是 m ! m! m!,所以得 C n m × m ! = A n m C_n^m\times m!=A_n^m Cnm×m!=Anm C n m = A n m m ! = n ! m ! ( n − m ) ! C_n^m=\frac{A_n^m}{m!}=\frac{n!}{m!(n-m)!} Cnm=m!Anm=m!(nm)!n!

组合数也经常用 ( n m ) \left(\begin{array}{c}n\\m\end{array}\right) (nm)表示,读作 n n n m m m,称为二项式系数

二项式定理

二项式定理阐明了一个展开式的系数:

( a + b ) n = ∑ i = 0 n ( n m ) a n − i b i (a+b)^n=\sum\limits_{i=0}^{n}\left(\begin{array}{c}n\\m\end{array}\right)a^{n-i}b^i (a+b)n=i=0n(nm)anibi

证明可以用 ( n k ) + ( n k − 1 ) = ( n + 1 k ) \left(\begin{array}{c}n\\k\end{array}\right)+\left(\begin{array}{c}n\\k-1\end{array}\right)=\left(\begin{array}{c}n+1\\k\end{array}\right) (nk)+(nk1)=(n+1k)

排列组合进阶

多重集的排列数 | 多重组合数

多重集是指包含重复元素的广义集合,设 S = { n 1 ⋅ a 1 , n 2 ⋅ a 2 , … , n k ⋅ a k } S=\{n_1\cdot a_1,n_2\cdot a_2,\dots,n_k\cdot a_k\} S={n1a1,n2a2,,nkak}表示由 n 1 n_1 n1 a 1 a_1 a1 n 2 n_2 n2 a 2 a_2 a2 … \dots n k n_k nk a k a_k ak组成的多重集, S S S的全排列个数为

n ! ∏ i = 1 k n i ! = n ! n 1 ! n 2 ! … n k ! \frac{n!}{\prod_{i=1}^{k}{n_i!}}=\frac{n!}{n_1!n_2!\dots n_k!} i=1kni!n!=n1!n2!nk!n!

指数型母函数

具体的 n = n 1 + n 2 + ⋯ + n k n=n_1+n_2+\dots+n_k n=n1+n2++nk,这 n n n个元素的全排列数就是多重集的排列数,也称为多重组合数,用符号表示为 ( n n 1 , n 2 , … , n k ) = n ! ∏ i = 1 k n i ! \left(\begin{array}{c}n\\n_1,n_2,\dots,n_k\end{array}\right)=\frac{n!}{\prod_{i=1}^k{n_i!}} (nn1,n2,,nk)=i=1kni!n!

若只对其中 r r r个元素进行排列呢,那就要用到指数型母函数。

构造母函数 G ( x ) = a 0 + a 1 1 ! x + a 2 2 ! x 2 + … G(x)=a_0+\frac{a_1}{1!}x+\frac{a_2}{2!}x^2+\dots G(x)=a0+1!a1x+2!a2x2+则称 G ( x ) G(x) G(x)是数列 a 0 , a 1 , … , a n a_0,a_1,\dots,a_n a0,a1,,an的指数型母函数

步骤
  1. 建立模型:物品 n n n种,每种数量分别为 k 1 , k 2 , … , k n k_1,k_2,\dots,k_n k1,k2,,kn个,求从中选出 m m m个物品的排列方法数

  2. 构造母函数:KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲G(x)&=(1+\frac{…

    其中系数 a i a_i ai为选出 i i i个物品的方案数

代码
double fib(int n) {
	double res = 1.0;
	for (int i = 1; i <= n; ++i) {
		res = res * i;
	}
	return res;
}
double a[maxn], f[maxn], g[maxn];
int main() {
	int n, m;
	while (~scanf("%d%d", &n, &m)) {
		memset(f, 0, sizeof(f));
		memset(g, 0, sizeof(g));
		for (int i = 0; i < n; ++i) {
			scanf("%lf", &a[i]);
		}
		for (int i = 0; i <= a[0]; ++i) {
			f[i] = 1.0 / fib(i);
		}
		for (int i = 1; i < n; ++i) {
			for (int j = 0; j <= m; ++j) {
				for (int k = 0; k <= a[i] && j + k <= m; ++k) {
					g[j + k] += f[j] / fib(k);
				}
			}
			for (int j = 0; j <= m; ++j) {
				f[j] = g[j]; g[j] = 0;
			}
		}
		printf("%.0lf\n", f[m] * fib(m));
	}
}

导引

x 1 + x 2 + ⋯ + x k = r x_1+x_2+\dots+x_k=r x1+x2++xk=r

相当于 1 … 1 ⏞ x 1 0 1 … 1 ⏞ x 2 0 … 0 1 … 1 ⏞ x k \overbrace{1\dots1}^{x_1}0\overbrace{1\dots1}^{x_2}0\dots0\overbrace{1\dots1}^{x_k} 11 x1011 x20011 xk r r r个1和 k − 1 k-1 k1个0的排列, ( r + k − 1 ) ! r ! ( k − 1 ) ! = ( r + k − 1 k − 1 ) = ( r + k − 1 r ) \frac{(r+k-1)!}{r!(k-1)!}=\left(\begin{array}{c}r+k-1\\k-1\end{array}\right)=\left(\begin{array}{c}r+k-1\\r\end{array}\right) r!(k1)!(r+k1)!=(r+k1k1)=(r+k1r)

多重集的组合数1

S = { n 1 ⋅ a 1 , n 2 ⋅ a 2 , … , n k ⋅ a k } S=\{n_1\cdot a_1,n_2\cdot a_2,\dots,n_k\cdot a_k\} S={n1a1,n2a2,,nkak}表示由 n 1 n_1 n1 a 1 a_1 a1 n 2 n_2 n2 a 2 a_2 a2 … \dots n k n_k nk a k a_k ak组成的多重集。那么对于整数 r ( r < n i , ⋁ i ⊂ [ 1 , k ] ) r(r<n_i,\bigvee i\subset[1, k]) r(r<ni,i[1,k]),从 S S S中选择 r r r个元素组成一个多重集的方案数就是多重集的组合数。等价于 x 1 + x 2 + ⋯ + x k = r x_1+x_2+\dots+x_k=r x1+x2++xk=r的非负整数解的数目,可以用插板法求解,答案为 ( r − k + 1 k − 1 ) \left(\begin{array}{c}r-k+1\\k-1\end{array}\right) (rk+1k1)

多重集的组合数2

S = { n 1 ⋅ a 1 , n 2 ⋅ a 2 , … , n k ⋅ a k } S=\{n_1\cdot a_1,n_2\cdot a_2,\dots,n_k\cdot a_k\} S={n1a1,n2a2,,nkak}表示由 n 1 n_1 n1 a 1 a_1 a1 n 2 n_2 n2 a 2 a_2 a2 … \dots n k n_k nk a k a_k ak组成的多重集。那么对于整数 r r r,从 S S S中选择 r r r个元素组成一个多重集的方案数。限制了每种元素取的个数,转换为带限制的线性方程求解: ∨ i ⊂ [ 1 , k ] , x i ≤ n i , ∑ i = 1 k x i = r \vee i\subset [1,k],x_i\leq n_i,\sum\limits_{i=1}^{k}x_i=r i[1,k]xinii=1kxi=r

容斥原理:

  1. 全集: ∑ i = 1 k x i = r \sum\limits_{i=1}^kx_i=r i=1kxi=r的非负整数解
  2. 属性: x i ≤ n i x_i\leq n_i xini

于是设满足属性 i i i的集合是 S i S_i Si S i ‾ \overline{S_i} Si表示不满足属性 i i i的集合,既满足 x i ≥ n i + 1 x_i\ge n_i+1 xini+1的集合。那么答案为 ∣ ⋂ i = 1 k S i ∣ = ∣ U ∣ − ∣ ⋃ i = 1 k S ‾ i ∣ |\bigcap\limits_{i=1}^kS_i|=|U|-|\bigcup\limits_{i=1}^k\overline S_i| i=1kSi=Ui=1kSi

根据容斥定理,有KaTeX parse error: No such environment: split at position 7: \begin{̲s̲p̲l̲i̲t̲}̲|\bigcup\limits…

令全集 ∣ U ∣ = ( k + r − 1 k − 1 ) |U|=\left(\begin{array}{c}k+r-1\\k-1\end{array}\right) U=(k+r1k1)

例子

  1. ( 0 , 0 ) (0,0) (0,0) ( m , n ) (m,n) (m,n)的非降路径数

    无论哪条路径,必须在 x x x方向走 m m m步, y y y方向走 n n n步,所以答案为 ( m + n ) ! m ! n ! = ( m + n m ) \frac{(m+n)!}{m!n!}=\left(\begin{array}{c}m+n\\m\end{array}\right) m!n!(m+n)!=(m+nm)

    一般的,设 c ≥ a , d ≥ b c\ge a,d\ge b ca,db,则由 ( a , b ) (a,b) (a,b) ( c , d ) (c,d) (c,d)的非降路径数为 ( c − a + d − b c − a ) \left(\begin{array}{c}c-a+d-b\\c-a\end{array}\right) (ca+dbca)

  2. r r r个相同的小球放入 n n n个不同的盒子,总共有多少种方案

    转换为 r r r个相同的小球与 n − 1 n-1 n1个杯壁的排列问题,即 ( r + n − 1 r ) \left(\begin{array}{c}r+n-1\\r\end{array}\right) (r+n1r)

  3. 求集合 X = { 1 , 2 , … , n } X=\{1,2,\dots,n\} X={1,2,,n}的不含相邻整数的 k k k元子集 S S S个数

    相当于有 0 , 1 0,1 0,1组成的有序 n n n重组,其中 1 1 1表示该元素属于 S S S,由于不含相邻整数,所以不含相邻的 1 1 1,则答案为 k k k个1, n − k n-k nk个0,先将0排列,后将1插空放置,则方案数为 ( n − k + 1 k ) \left(\begin{array}{c}n-k+1\\k\end{array}\right) (nk+1k)

不相邻的排列

1 ∼ n 1\sim n 1n n n n个自然数之间选 k k k个,这 k k k个数中任意两个数不相邻的组合有 ( n − k + 1 k ) \left(\begin{array}{c}n-k+1\\k\end{array}\right) (nk+1k)种。

错位排列

要求位置放置的编号不同,有多少种不同的放置方法。

假设考虑第 n n n个位置,初始我们把编号 n n n放在第 n n n个位置,然后考虑两种情况:

  • 前面 n − 1 n-1 n1个位置都不同
  • 前面 n − 1 n-1 n1个位置只有一个相同

第一种情况,编号 n n n只需要与前面任一个位置交换即可,共有 f ( n − 1 ) × ( n − 1 ) f(n-1)\times(n-1) f(n1)×(n1)种情况

第二种情况,将相同的编号与 n n n交换即可,共有 f ( n − 1 ) × ( n − 2 ) f(n-1)\times(n-2) f(n1)×(n2)种情况

所以,错位排列的方案数为 f ( n ) = ( n − 1 ) ( f ( n − 1 ) + f ( n − 2 ) ) f(n)=(n-1)(f(n-1)+f(n-2)) f(n)=(n1)(f(n1)+f(n2))

圆排列

n n n个人排成一圈,所有的排列数记为 Q n n Q_n^n Qnn。考虑已经排好的一圈,从不同位置断开,都会形成不同的队列。所以有

Q n n × n = A n n ⟹ Q n = A n n n = ( n − 1 ) ! \mathrm Q_n^n\times n=\mathrm A_n^n\Longrightarrow\mathrm Q_n=\frac{\mathrm A_n^n}{n}=(n-1)! Qnn×n=AnnQn=nAnn=(n1)!

组合数性质 | 二项式推论

对称性: ( n m ) = ( n n − m ) \left(\begin{array}{c}n\\m\end{array}\right)=\left(\begin{array}{c}n\\n-m\end{array}\right) (nm)=(nnm)

递推式: ( n k ) = n k ( n − 1 k − 1 ) \left(\begin{array}{c}n\\k\end{array}\right)=\frac{n}{k}\left(\begin{array}{c}n-1\\k-1\end{array}\right) (nk)=kn(n1k1)

杨辉三角: ( n m ) = ( n − 1 m ) + ( n − 1 m − 1 ) \left(\begin{array}{c}n\\m\end{array}\right)=\left(\begin{array}{c}n-1\\m\end{array}\right)+\left(\begin{array}{c}n-1\\m-1\end{array}\right) (nm)=(n1m)+(n1m1),用来 O ( n 2 ) O(n^2) O(n2)递推

特殊情况: ( n 0 ) + ( n 1 ) + ⋯ + ( n n ) = ∑ i = 0 n ( n i ) = 2 n \left(\begin{array}{c}n\\0\end{array}\right)+\left(\begin{array}{c}n\\1\end{array}\right)+\dots+\left(\begin{array}{c}n\\n\end{array}\right)=\sum\limits_{i=0}^n\left(\begin{array}{c}n\\i\end{array}\right)=2^n (n0)+(n1)++(nn)=i=0n(ni)=2n

另一个特殊情况: ∑ i = 0 n ( − 1 ) i ( n i ) = 0 \sum\limits_{i=0}^n(-1)^i\left(\begin{array}{c}n\\i\end{array}\right)=0 i=0n(1)i(ni)=0

组合数的拆分(数据结构题目): ∑ i = 0 m ( n i ) ( m m − i ) = ( m + n m ) \sum\limits_{i=0}^m\left(\begin{array}{c}n\\i\end{array}\right)\left(\begin{array}{c}m\\m-i\end{array}\right)=\left(\begin{array}{c}m+n\\m\end{array}\right) i=0m(ni)(mmi)=(m+nm),相当于原本从 m + n m+n m+n个人中选 m m m个人,相当于从 n n n个人里面选 i i i个,再从 m m m人里面选另外的 m − i m-i mi个人。

​ 取 n = m n=m n=m,得 ∑ i = 0 n ( n i ) 2 = ( 2 n n ) \sum\limits_{i=0}^n\left(\begin{array}{c}n\\i\end{array}\right)^2=\left(\begin{array}{c}2n\\n\end{array}\right) i=0n(ni)2=(2nn)

带权和: ∑ i = 0 n i ( n i ) = n 2 n − 1 \sum\limits_{i=0}^ni\left(\begin{array}{c}n\\i\end{array}\right)=n2^{n-1} i=0ni(ni)=n2n1

​ 平方和: ∑ i = 0 n i 2 ( n i ) = n ( n + 1 ) 2 n − 2 \sum\limits_{i=0}^ni^2\left(\begin{array}{c}n\\i\end{array}\right)=n(n+1)2^{n-2} i=0ni2(ni)=n(n+1)2n2

恒等式证明: ∑ l = 0 n ( l k ) = ( n + 1 k + 1 ) \sum\limits_{l=0}^n\left(\begin{array}{c}l\\k\end{array}\right)=\left(\begin{array}{c}n+1\\k+1\end{array}\right) l=0n(lk)=(n+1k+1),考虑 S = a 1 , a 2 , … , a n + 1 S=a_1,a_2,\dots,a_{n+1} S=a1,a2,,an+1 k + 1 k+1 k+1子集数得证

( n r ) ( r k ) = ( n k ) ( n − k r − k ) \left(\begin{array}{c}n\\r\end{array}\right)\left(\begin{array}{c}r\\k\end{array}\right)=\left(\begin{array}{c}n\\k\end{array}\right)\left(\begin{array}{c}n-k\\r-k\end{array}\right) (nr)(rk)=(nk)(nkrk)

∑ k = 1 m ( m k ) ( n k ) = ( m + n m ) \sum\limits_{k=1}^m\left(\begin{array}{c}m\\k\end{array}\right)\left(\begin{array}{c}n\\k\end{array}\right)=\left(\begin{array}{c}m+n\\m\end{array}\right) k=1m(mk)(nk)=(m+nm)

∑ i = 0 n ( n − i i ) = F n + 1 \sum\limits_{i=0}^n\left(\begin{array}{c}n-i\\i\end{array}\right)=F_{n+1} i=0n(nii)=Fn+1,其中 F F F为斐波那契数列

卡塔兰数

卡塔兰数是组合数学中一个常在各种计数问题中出现的数列。

卡塔兰数的一般项公式为 C n = 1 n + 1 ( 2 n n ) = ( 2 n ) ! ( n + 1 ) ! n ! C_n=\frac{1}{n+1}{2n\choose n}=\frac{(2n)!}{(n+1)!n!} Cn=n+11(n2n)=(n+1)!n!(2n)!,前10项卡塔兰数为 1 , 1 , 2 , 5 , 14 , 42 , 132 , 429 , 1430 , 4862 1,1,2,5,14,42,132,429,1430,4862 1,1,2,5,14,42,132,429,1430,4862

性质

C n C_n Cn的另一个表达式: C n = ( 2 n n ) − ( 2 n n + 1 ) , n ≥ 1 C_n={2n\choose n}-{2n\choose n+1},n\ge 1 Cn=(n2n)(n+12n),n1

递推关系: C 0 = 1 ,    C n + 1 = ∑ i = 0 n C i C n − i C_0=1,\;C_{n+1}=\sum\limits_{i=0}^nC_iC_{n-i} C0=1,Cn+1=i=0nCiCni

​ 它也满足: C 0 = 1 ,    C n + 1 = 2 ( 2 n + 1 ) n + 2 C n C_0=1,\;C_{n+1}=\frac{2(2n+1)}{n+2}C_n C0=1,Cn+1=n+22(2n+1)Cn

卡塔兰数的渐进增长为: C n ∼ 4 n n 3 / 2 π C_n\sim\frac{4^n}{n^{3/2}\sqrt{\pi}} Cnn3/2π 4n

母函数

卡塔兰数的母函数为 M ( z ) = ∑ C n z n M(z)=\sum C_nz^n M(z)=Cnzn,则 M ( z ) = 1 + z M ( z ) 2 M(z)=1+zM(z)^2 M(z)=1+zM(z)2

应用

  • C n C_n Cn表示长度 2 n 2n 2n的满足n个X和n个Y组成的字串,且所有的前缀字串皆满足X的个数大于等于Y的个数。以下满足条件的长度为6字串:XXXYYY XYXXYY XYXYXY XXYYXY XXYXYY

  • 将上例X换成左括号,Y换成右括号, C n C_n Cn表示所有包含n组括号的合法运算式的个数:((())) ()(()) ()()() (())() (()())

  • C n C_n Cn表示有n个节点组成的不同构二叉树的方案数

  • C n C_n Cn表示有2n+1个节点组成不同构满二叉树的方案数

    证明:令1表示进栈,0表示出栈,则可转化为求一个2n位、含n个1、n个0的二进制数,满足从左到右扫描到任意一位时,经过的0数不多于1数。显然含n个1、n个0的2n位二进制数共有 ( 2 n n ) {2n\choose n} (n2n)个,考虑减去不满足要求的数目。

    考虑一个含n个1、n个0的2n位二进制数,扫描到第2m+1位上时有m+1个0和m个1(一定存在这种情况),则后面的0-1排列中必有n-m个1和n-m-1个0。将2m+2及其以后的部分0变成1、1变成0,则对应一个存在n+1个0和n-1个1的二进制数。从而 C n = ( 2 n n ) − ( 2 n n + 1 ) = 1 n + 1 ( 2 n n ) C_n={2n\choose n}-{2n\choose n+1}=\frac{1}{n+1}{2n\choose n} Cn=(n2n)(n+12n)=n+11(n2n)

  • C n C_n Cn表示所有 n × n n\times n n×n格点中不越过对角线的单调路径的个数。一个单调路径从左下角出发,右上角结束,每一步均为向上或向右。计算这种路径相当于计算第一种字串的数目:X代表向右,Y代表向上

  • C n C_n Cn表示通过连接顶点而将 n + 2 n+2 n+2边的凸多边形分成三角形的方法个数。

  • C n C_n Cn表示对 { 1 , 2 , … , n } \{1,2,\dots,n\} {1,2,,n}依次进入的置换个数。

母函数

某个序列 ( a n ) n ∈ N (a_n)n\in\N (an)nN的母函数是一种形式幂级数,其每一项的系数可以提供关于这个序列的信息

母函数分为很多种,包括普通母函数、指数母函数、L级数、贝尔级数和狄利克雷级数。对每个序列都可以写出以上每个类型的一个母函数。

构造母函数的目的是为了解决某个特定的问题,因此选用何种母函数视乎序列本身的特性和问题的类型。

普通母函数

引入

当投掷n粒骰子时,加起来点数总和等于m的可能方式的数目

采用母函数方法得出可能的数目是 ( x + x 2 + x 3 + x 4 + x 5 + x 6 ) n (x+x^2+x^3+x^4+x^5+x^6)^n (x+x2+x3+x4+x5+x6)n的展开式中 x m x^m xm项的系数。

有1克、2克、3克、4克的砝码各一枚,求能称出多少种重量

每种砝码有选和不选的两种状态,包含全不选共 2 4 = 16 2^4=16 24=16种方案数

在多项式里,系数是不同项的积的和,而这里我们要计算的重量的和,因此我们可以用幂运算来表示。因此可以表示为 ( x 0 + x 1 ) ( x 0 + x 2 ) ( x 0 + x 3 ) ( x 0 + x 4 ) (x^0+x^1)(x^0+x^2)(x^0+x^3)(x^0+x^4) (x0+x1)(x0+x2)(x0+x3)(x0+x4)= x 0 + x 1 + x 2 + 2 x 3 + 2 x 4 + 2 x 5 + 2 x 6 + 2 x 7 + x 8 + x 9 + x 10 x^0+x^1+x^2+2x^3+2x^4+2x^5+2x^6+2x^7+x^8+x^9+x^{10} x0+x1+x2+2x3+2x4+2x5+2x6+2x7+x8+x9+x10,每一项 a i x i a_ix^i aixi的系数为重量为 i i i的方案数为 a i a_i ai,故结果为系数和

概念

普通母函数就是最常见的母函数。一般来说,序列 ( a n ) n ∈ N (a_n)n\in\N (an)nN的母函数为: G ( a n ; x ) = ∑ n = 0 ∞ a n x n G(a_n;x)=\sum\limits_{n=0}^{\infin}a_nx^n G(an;x)=n=0anxn

引申

求用1克、2克、3克的砝码称出 x x x克的方案数

这个地方砝码的数量是无限的,母函数表示为 ( x 0 + x 1 + x 2 + …   ) (x^0+x^1+x^2+\dots) (x0+x1+x2+) ( x 0 + x 2 + x 4 + …   ) (x^0+x^2+x^4+\dots) (x0+x2+x4+) ( x 0 + x 3 + x 6 + …   ) (x^0+x^3+x^6+\dots) (x0+x3+x6+),结果也是无限的。但对于给定的 x x x,我们只需要维护 a i x i a_ix^i aixi,其中 i ≤ x i\leq x ix的部分。

代码

求给出重量为 1 ∼ 6 1\sim6 16的物品的个数,求是否能把物品分成重量相同的两堆

const int maxn = 6e3 + 5;
int a[10];
int f[maxn], g[maxn];
bool check(int limit) {
	memset(f, 0, sizeof(f));
	memset(g, 0, sizeof(g));
	for (int i = 0; i <= a[1]; ++i) f[i] = 1;
	for (int i = 2; i <= 6; ++i) {
		for (int j = 0; j <= limit; ++j) {
			for (int k = 0; k <= a[i] && j + i * k <= limit; ++k) {
				g[j + i * k] += f[j];
			}
		}
		for (int j = 0; j <= limit; ++j) {
			f[j] = g[j]; g[j] = 0;
		}
	}
	return f[limit] ? true : false;
}
int main()
{
	for (int cas = 1; ; ++cas) {
		int sum = 0;
		for (int i = 1; i <= 6; ++i) {
			scanf("%d", &a[i]);
			if (a[i] >= 8)
				a[i] = a[i] & 1 ? 11 : 12;
			sum += i * a[i];
		}
		if (sum == 0) break;
		printf("Collection #%d:\n", cas);
		if (sum & 1) printf("Can't be divided.\n\n");
		else printf("%s\n\n", check(sum / 2) ? "Can be divided." : "Can't be divided.");
	}
}

指数型母函数

对于序列 a 0 , a 1 , … a_0,a_1,\dots a0,a1,,函数 G e ( x ) = a 0 + a 1 1 ! x + a 2 2 ! x 2 + ⋯ + a k k ! x k + … G_e(x)=a_0+\frac{a_1}{1!}x+\frac{a_2}{2!}x^2+\dots+\frac{a_k}{k!}x^k+\dots Ge(x)=a0+1!a1x+2!a2x2++k!akxk+称为序列 a 0 , a 1 , a 2 , … a_0,a_1,a_2,\dots a0,a1,a2,对应的指数型母函数

指数型母函数用来解决多重集的排列问题

步骤

  1. 建立模型:物品 n n n种,每种数量分别为 k 1 , k 2 , … , k n k_1,k_2,\dots,k_n k1,k2,,kn个,求从中选出 m m m个物品的排列方法数

  2. 构造母函数:KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲G(x)&=(1+\frac{…

    其中系数 a i a_i ai为选出 i i i个物品的方案数

代码
double fib(int n) {
	double res = 1.0;
	for (int i = 1; i <= n; ++i) {
		res = res * i;
	}
	return res;
}
double a[maxn], f[maxn], g[maxn];
int main() {
	int n, m;
	while (~scanf("%d%d", &n, &m)) {
		memset(f, 0, sizeof(f));
		memset(g, 0, sizeof(g));
		for (int i = 0; i < n; ++i) {
			scanf("%lf", &a[i]);
		}
		for (int i = 0; i <= a[0]; ++i) {
			f[i] = 1.0 / fib(i);
		}
		for (int i = 1; i < n; ++i) {
			for (int j = 0; j <= m; ++j) {
				for (int k = 0; k <= a[i] && j + k <= m; ++k) {
					g[j + k] += f[j] / fib(k);
				}
			}
			for (int j = 0; j <= m; ++j) {
				f[j] = g[j]; g[j] = 0;
			}
		}
		printf("%.0lf\n", f[m] * fib(m));
	}
}

优化

泰勒展开和 e x e^x ex的幂级数 f ( x ) = e x , f ′ ( x ) = e x , f ′ ′ ( x ) = e x , … , f n ( x ) = e x f(x)=e^x,f'(x)=e^x,f''(x)=e^x,\dots,f^n(x)=e^x f(x)=ex,f(x)=ex,f(x)=ex,,fn(x)=ex e x = ∑ n = 0 ∞ 1 n ! x n e^x=\sum\limits_{n=0}^\infin\frac{1}{n!}x^n ex=n=0n!1xn

例子

h R ( x ) = 1 + x 2 2 ! + x 4 4 ! + x 6 6 ! + … h_R(x)=1+\frac{x^2}{2!}+\frac{x^4}{4!}+\frac{x^6}{6!}+\dots hR(x)=1+2!x2+4!x4+6!x6+

h B ( x ) = 1 + x 1 ! + x 2 2 ! + x 3 3 ! + … h_B(x)=1+\frac{x}{1!}+\frac{x^2}{2!}+\frac{x^3}{3!}+\dots hB(x)=1+1!x+2!x2+3!x3+

h G ( x ) = 1 + x 2 2 ! + x 4 4 ! + x 6 6 ! + … h_G(x)=1+\frac{x^2}{2!}+\frac{x^4}{4!}+\frac{x^6}{6!}+\dots hG(x)=1+2!x2+4!x4+6!x6+

h Y ( x ) = 1 + x 1 ! + x 2 2 ! + x 3 3 ! + … h_Y(x)=1+\frac{x}{1!}+\frac{x^2}{2!}+\frac{x^3}{3!}+\dots hY(x)=1+1!x+2!x2+3!x3+

KaTeX parse error: No such environment: align at position 7: \begin{̲a̲l̲i̲g̲n̲}̲g^e(x)&=h_R(x)h…

代入 e k x = ∑ i = 0 ∞ k n x n n ! e^{kx}=\sum\limits_{i=0}^\infin\frac{k^nx^n}{n!} ekx=i=0n!knxn,得 g e ( x ) = 1 4 + ∑ i = 0 ∞ ( 4 i + 2 i + 1 ) x i i ! g^e(x)=\frac{1}{4}+\frac{\sum\limits_{i=0}^\infin(4^i+2^{i+1})x^i}{i!} ge(x)=41+i!i=0(4i+2i+1)xi

所以得第 k k k项系数为 4 i − 1 + 2 i 4^{i-1}+2^i 4i1+2i

e x + e − x e^x+e^{-x} ex+ex消去奇数项

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值