母函數就是一列用來展示一串數字的掛衣架。 ——赫伯特·唯爾夫 。
一、普通型母函數
1.定義
對於任意數列a 0 , a 1 , a 2 . . . a n a_0,a_1,a_2...a_n a 0 , a 1 , a 2 . . . a n ,用如下方法與一個函數聯繫起來:
G ( x ) = a 0 + a 1 x + a 2 x 2 + . . . + a n x n
G(x) = a_0+a_1x+a_2x^2+...+a_nx^n
G ( x ) = a 0 + a 1 x + a 2 x 2 + . . . + a n x n
則稱G ( x ) G(x) G ( x ) 是數列的母函數(generating function)(也叫生成函數)。
其一般形式爲:
G ( a n ; x ) = ∑ i = 1 a i x i
\displaystyle G(a_n;x)=\sum_{i=1}a_ix^i
G ( a n ; x ) = i = 1 ∑ a i x i
2.應用
組合數學的主要內容是計數,母函數是組合數學中的一個重要理論和工具。那麼它是怎麼應用的呢?
普 通 型 母 函 數 主 要 是 解 決 求 有 限 多 重 集 的 組 合 普通型母函數主要是解決求有限多重集的組合 普 通 型 母 函 數 主 要 是 解 決 求 有 限 多 重 集 的 組 合
設元素 a 1 , a 1 , ⋅ ⋅ ⋅ , a n a_{1},a_{1}, \cdot \cdot \cdot ,a_{n} a 1 , a 1 , ⋅ ⋅ ⋅ , a n 互不相同,從有限多重集{ K 1 ⋅ a 1 , K 2 ⋅ a 2 , ⋅ ⋅ ⋅ K n ⋅ a n } \left\{ K_{1} \cdot a_{1},K_{2} \cdot a_{2}, \cdot \cdot \cdot K_{n} \cdot a_{n} \right\} { K 1 ⋅ a 1 , K 2 ⋅ a 2 , ⋅ ⋅ ⋅ K n ⋅ a n } 中選取 r r r 個元素,至少存在一個K i < r K_{i} < r K i < r 時,求其組合。
下面舉一個應用實例來理解這個問題:
現在我有兩個色子,每個色子有六個面,每個色子擲一次,問兩個色子投擲後加起來一共六點的情況有多少種?
我們數一數,根據加法原理:
6 = 1 + 5 = 5 +1
6= 2 + 4 = 4 + 2
6 = 3 + 3
根據乘法原理
第一次取 1,2,3,4,5 共五種方式
由於第一次已經取好,所以第二次的取法是固定的 只有一種
綜上,加起來點數爲 6 一共是 五 種。
但是如果有 n n n 個色子呢?顯然就很難這樣計算出來了
我們這時就需要母函數了。
我們可以 x , x 2 , x 3 , x 4 , x 5 , x 6 x,x^2,x^3,x^4,x^5,x^6 x , x 2 , x 3 , x 4 , x 5 , x 6 和 色子的 1 , 2 , 3 , 4 , 5 , 6 1,2,3,4,5,6 1 , 2 , 3 , 4 , 5 , 6 點映射對應起來。
按照乘法原理,我們可以將兩次 色子的投擲看成是 兩個 多項式相乘。
例如 投擲 6 點
第一次 投的 是 4 點,第二次是 2 點。和 x 4 x 2 = x 6 x^4 x^2=x^6 x 4 x 2 = x 6 對應起來。
那麼第一次投擲可能取1 , 2 , 3 , 4 , 5 , 6 1,2,3,4,5,6 1 , 2 , 3 , 4 , 5 , 6 點,這些情況是不可能同時發生的,那麼根據加法原理:
第一次投擲就可以和 多項式( x + x 2 + x 3 + x 4 + x 5 + x 6 ) (x+x^2+x^3+x^4+x^5+x^6) ( x + x 2 + x 3 + x 4 + x 5 + x 6 ) 形成一個映射關係,x i x^i x i 就表示投擲出了 i i i 點。
那麼兩次投擲的過程就能表示爲兩個多項式的乘積:
( x + x 2 + x 3 + x 4 + x 5 + x 6 ) ∗ ( x + x 2 + x 3 + x 4 + x 5 + x 6 ) (x+x^2+x^3+x^4+x^5+x^6)*(x+x^2+x^3+x^4+x^5+x^6) ( x + x 2 + x 3 + x 4 + x 5 + x 6 ) ∗ ( x + x 2 + x 3 + x 4 + x 5 + x 6 )
乘積的結果是
x 2 + 2 x 3 + 3 x 4 + 4 x 5 + 5 x 6 + 6 x 7 + 5 x 8 + 4 x 9 + 3 x 10 + 2 x 11 + x 12 x^2+2x^3+3x^4+4x^5+5x^6+6x^7+5x^8+4x^9+3x^{10}+2x^{11}+x^{12} x 2 + 2 x 3 + 3 x 4 + 4 x 5 + 5 x 6 + 6 x 7 + 5 x 8 + 4 x 9 + 3 x 1 0 + 2 x 1 1 + x 1 2
x 6 : x 1 x 5 + x 2 + x 4 + x 3 x 3 + x 4 x 2 + x 5 x 1 = 5 x 6 x^6:x^1x^5+x^2+x^4+x^3x^3+x^4x^2+x^5x^1=5x^6 x 6 : x 1 x 5 + x 2 + x 4 + x 3 x 3 + x 4 x 2 + x 5 x 1 = 5 x 6
我們發現 x 6 x^6 x 6 的係數就是兩次投擲點數和爲 6 的方法數。
到此我們可以得到一個結論:
投擲 m m m 粒色子時,加起來點數的綜合化等於n n n 的可能方式的數目爲:
G ( x ) = ( x + x 2 + x 3 + x 4 + x 5 + x 6 ) m G(x)=(x+x^2+x^3+x^4+x^5+x^6)^m G ( x ) = ( x + x 2 + x 3 + x 4 + x 5 + x 6 ) m
展開式中x n x^n x n 的係數。
很明顯G ( x ) G(x) G ( x ) 就是序列{ 1 , 2 , 3 , 4 , 5 , 6 } \{1,2,3,4,5,6\} { 1 , 2 , 3 , 4 , 5 , 6 } 的一個母函數,這個例子也很好的說明了母函數的應用:
將計數問題映射成多項式的乘法運算來解決
HDU 1028 Ignatius and the Princess II
題意
給定一個數N N N ,問N N N 拆成若干個整數有多少中拆分方法?
思路
使用母函數進行映射
取 0 個1 1 1 : x 0 x^0 x 0
取 1 個1 1 1 : x 1 x^1 x 1
取 2 個1 1 1 : x 2 x^2 x 2
取 1 1 1 對應的母函數: ( 1 + x + x 2 + . . . + x k + . . . ) (1+x+x^2+...+x^k+...) ( 1 + x + x 2 + . . . + x k + . . . )
取 2 2 2 對應的母函數: ( 1 + x 1 + x 4 + . . . + x 2 k . . . ) (1+x^1+x^4+...+x^{2k}...) ( 1 + x 1 + x 4 + . . . + x 2 k . . . )
G ( x ) = ( 1 + x + x 2 + . . . ) ( 1 + x 2 + x 4 + . . . ) ( 1 + x 2 + x 4 + . . . ) ( 1 + x N ) G(x) = (1+x+x^2+...)(1+x^2+x^4+...)(1+x^2+x^4+...)(1+x^N) G ( x ) = ( 1 + x + x 2 + . . . ) ( 1 + x 2 + x 4 + . . . ) ( 1 + x 2 + x 4 + . . . ) ( 1 + x N )
x N x^N x N 的係數就是 我們要求的答案。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
using namespace std;
const int N = 1000 ;
ll a[ N] , b[ N] ;
int n;
void mother_fun ( )
{
a[ 0 ] = 1 ;
for ( int i = 1 ; i <= n ; i++ )
{
memset ( b, 0 , sizeof ( b) ) ;
for ( int j = 0 ; j * i <= n; j++ )
{
for ( int k = 0 ; k <= n; k++ )
{
b[ i * j + k] + = a[ k] ;
}
}
memcpy ( a, b, sizeof ( b) ) ;
}
}
int main ( )
{
while ( scanf ( "%d" , & n) != EOF )
{
memset ( a, 0 , sizeof ( a) ) ;
mother_fun ( ) ;
printf ( "%lld\n" , a[ n] ) ;
}
return 0 ;
}
二、指數型母函數
1.定義
序列a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a 1 , a 2 , . . . , a n 的指數型母函數爲:
E G ( a n ; x ) = ∑ i = 0 a i x i i ! \displaystyle EG(a_n;x)=\sum_{i = 0}a_i\frac{x^i}{i!} E G ( a n ; x ) = i = 0 ∑ a i i ! x i
2.應用
從上面的學習,我們可以知道:普通型的母函數是一個解決求有限多重集的組合的有效工具,而指數型函數是
指 數 型 母 函 數 主 要 是 解 決 求 有 限 多 重 集 的 排 列 指數型母函數主要是解決求有限多重集的排列 指 數 型 母 函 數 主 要 是 解 決 求 有 限 多 重 集 的 排 列
設元素a 1 , a 1 , ⋅ ⋅ ⋅ , a n a_{1},a_{1}, \cdot \cdot \cdot ,a_{n} a 1 , a 1 , ⋅ ⋅ ⋅ , a n 互不相同,從有限多重集{ K 1 ⋅ a 1 , K 2 ⋅ a 2 , ⋅ ⋅ ⋅ K n ⋅ a n } \left\{ K_{1} \cdot a_{1},K_{2} \cdot a_{2}, \cdot \cdot \cdot K_{n} \cdot a_{n} \right\} { K 1 ⋅ a 1 , K 2 ⋅ a 2 , ⋅ ⋅ ⋅ K n ⋅ a n } 中選取 r r r 個元素,至少存在一個K i < r K_{i} < r K i < r 時,求其排列。
我們比較普通型母函數和指數型母函數,可以看出普通型的母函數的標誌函數爲1 , x , x 2 , . . . , x n 1,x,x^2,...,x^n 1 , x , x 2 , . . . , x n ;而指數型函數的標誌函數爲1 , x / 1 ! , x 2 / 2 ! , x 3 / 3 ! . . . , x n / n ! 1,x/1!,x^2/2!,x^3/3!...,x^n/n! 1 , x / 1 ! , x 2 / 2 ! , x 3 / 3 ! . . . , x n / n ! 。
這樣的映射也有其意義:
x i i ! \displaystyle\frac{x^i}{i!} i ! x i 代表的意義是:在某個方案中某個元素出現了 i i i 次,而在不同位置中的 i i i 次出現是相同的。
另外,在指數型母函數使用的過程中,一般都會用到高等數學裏的e x e^x e x 的泰勒展開式:
e x = ∑ n = 0 x n n ! = 1 + x + x 2 2 ! + x 3 3 ! . . . + x n n ! + . . . e^x=\sum_{n=0}\frac{x^n}{n!}=1 + x+\frac{x^2}{2!}+\frac{x^3}{3!}...+\frac{x^n}{n!}+... e x = n = 0 ∑ n ! x n = 1 + x + 2 ! x 2 + 3 ! x 3 . . . + n ! x n + . . .
( e x + e − x ) / 2 = ∑ n = 0 x 2 n 2 n ! = 1 + x 2 2 ! + x 4 4 ! . . . + x 2 n 2 n ! + . . . (e^x+e^{-x})/2=\sum_{n=0}\frac{x^{2n}}{2n!}=1 +\frac{x^2}{2!}+\frac{x^4}{4!}...+\frac{x^{2n}}{2n!}+... ( e x + e − x ) / 2 = n = 0 ∑ 2 n ! x 2 n = 1 + 2 ! x 2 + 4 ! x 4 . . . + 2 n ! x 2 n + . . .
( e x − e − x ) / 2 = ∑ n = 0 x 2 n + 1 ( 2 n + 1 ) ! = x + x 3 3 ! + x 5 5 ! . . . + x 2 n + 1 ( 2 n + 1 ) ! + . . . (e^x-e^{-x})/2=\sum_{n=0}\frac{x^{2n+1}}{(2n+1)!}= x+\frac{x^3}{3!}+\frac{x^5}{5!}...+\frac{x^{2n+1}}{(2n+1)!}+... ( e x − e − x ) / 2 = n = 0 ∑ ( 2 n + 1 ) ! x 2 n + 1 = x + 3 ! x 3 + 5 ! x 5 . . . + ( 2 n + 1 ) ! x 2 n + 1 + . . .
下面來舉個例子:
由1 , 2 , 3 , 4 1,2,3,4 1 , 2 , 3 , 4 四個數字組成的五位數中,要求數 1 1 1 出現兩次或三次,2 2 2 最多出現一次,4 4 4 出現偶數次。
這很明顯是一個排列數的問題,在我們有了上述普通型母函數的經驗之後,我們可以類似地開始構造我們的指數型母函數:
1 1 1 出現兩次或三次,對應的母函數:x 2 2 ! + x 3 3 ! \displaystyle\frac{x^2}{2!}+\frac{x^3}{3!} 2 ! x 2 + 3 ! x 3
2 2 2 最多出現 一次,對應的母函數:1 + x 1 ! \displaystyle1+\frac{x}{1!} 1 + 1 ! x
3 3 3 出現沒有要求, 1 + x 1 ! + x 2 2 ! + x 3 3 ! + . . . + x n n ! + . . . \displaystyle1+ \frac{x}{1!}+ \frac{x^2}{2!} +\frac{x^3}{3!}+...+\frac{x^{n}}{n!}+... 1 + 1 ! x + 2 ! x 2 + 3 ! x 3 + . . . + n ! x n + . . .
4 4 4 出現偶數次, 1 + x 2 2 ! + x 4 4 ! + x 6 6 ! . . . + x 2 n 2 n ! + . . . \displaystyle1+\frac{x^2}{2!} +\frac{x^4}{4!}+\frac{x^6}{6!}...+\frac{x^{2n}}{2n!}+... 1 + 2 ! x 2 + 4 ! x 4 + 6 ! x 6 . . . + 2 n ! x 2 n + . . .
那麼本題的母函數:
G ( x ) = ( x 2 2 ! + x 3 3 ! ) ∗ ( 1 + x 1 ! ) ∗ ( 1 + x 1 ! + x 2 2 ! + x 3 3 ! + . . . + x n n ! + . . . ) ∗ ( 1 + x 2 2 ! + x 4 4 ! + x 6 6 ! . . . + x 2 n 2 n ! + . . . ) \displaystyle G(x) = (\frac{x^2}{2!}+\frac{x^3}{3!})*(1+\frac{x}{1!})*(1+ \frac{x}{1!}+ \frac{x^2}{2!} +\frac{x^3}{3!}+...+\frac{x^{n}}{n!}+...)*(1+\frac{x^2}{2!} +\frac{x^4}{4!}+\frac{x^6}{6!}...+\frac{x^{2n}}{2n!}+...) G ( x ) = ( 2 ! x 2 + 3 ! x 3 ) ∗ ( 1 + 1 ! x ) ∗ ( 1 + 1 ! x + 2 ! x 2 + 3 ! x 3 + . . . + n ! x n + . . . ) ∗ ( 1 + 2 ! x 2 + 4 ! x 4 + 6 ! x 6 . . . + 2 n ! x 2 n + . . . )
因爲,e x = ∑ n = 0 x n n ! = 1 + x + x 2 2 ! + x 3 3 ! . . . + x n n ! + . . . e^x=\sum_{n=0}\frac{x^n}{n!}=1 + x+\frac{x^2}{2!}+\frac{x^3}{3!}...+\frac{x^n}{n!}+... e x = n = 0 ∑ n ! x n = 1 + x + 2 ! x 2 + 3 ! x 3 . . . + n ! x n + . . .
( e x + e − x ) / 2 = ∑ n = 0 x 2 n 2 n ! = 1 + x 2 2 ! + x 4 4 ! . . . + x 2 n 2 n ! + . . . (e^x+e^{-x})/2=\sum_{n=0}\frac{x^{2n}}{2n!}=1 +\frac{x^2}{2!}+\frac{x^4}{4!}...+\frac{x^{2n}}{2n!}+... ( e x + e − x ) / 2 = n = 0 ∑ 2 n ! x 2 n = 1 + 2 ! x 2 + 4 ! x 4 . . . + 2 n ! x 2 n + . . .
所以
G ( x ) = ( x 2 2 ! + x 3 3 ! ) ∗ ( 1 + x 1 ! ) ∗ e x ∗ ( e x + e − x ) / 2 G(x)=(\frac{x^2}{2!}+\frac{x^3}{3!})*(1+\frac{x}{1!})*e^x*(e^x+e^{-x})/2 G ( x ) = ( 2 ! x 2 + 3 ! x 3 ) ∗ ( 1 + 1 ! x ) ∗ e x ∗ ( e x + e − x ) / 2
= ( x 2 4 + x 3 3 + x 4 12 ) ∗ ( e 2 x + 1 ) =\displaystyle(\frac{x^2}{4}+\frac{x^3}{3}+\frac{x^4}{12})*(e^{2x}+1) = ( 4 x 2 + 3 x 3 + 1 2 x 4 ) ∗ ( e 2 x + 1 )
我們要求的是 5 5 5 位數,那麼我們的答案就應該是x 5 5 ! \displaystyle\frac{x^5}{5!} 5 ! x 5 前面的係數。
我們已經有了x 2 , x 3 , x 4 x^2,x^3,x^4 x 2 , x 3 , x 4 ,所以只需要補上x 3 , x 2 , x 1 x^3,x^2,x^1 x 3 , x 2 , x 1
將e 2 x e^{2x} e 2 x 按泰勒展開後,可以得到係數是:
5 ! ∗ ( 1 4 ∗ 2 3 3 ! + 1 2 ∗ 2 2 2 ! + 1 12 ∗ 2 1 1 ! ) = 140 5!*(\frac{1}{4}*\frac{2^3}{3!}+\frac{1}{2}*\frac{2^2}{2!}+\frac{1}{12}*\frac{2^1}{1!})=140 5 ! ∗ ( 4 1 ∗ 3 ! 2 3 + 2 1 ∗ 2 ! 2 2 + 1 2 1 ∗ 1 ! 2 1 ) = 1 4 0
HDU 1521 排列組合
題意
有n種物品,並且知道每種物品的數量。要求從中選出m件物品的排列數。例如有兩種物品A,B,並且數量都是1,從中選2件物品,則排列有"AB","BA"兩種。
思路
根據題意,這是一個多重集的排列數問題,所以考慮使用指數型生成函數,然後就是一頓模板。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define ll long long
using namespace std;
const int N = 107 ;
int n, m;
int num[ N] ;
double a[ N] = { 0 } , b[ N] = { 0 } ;
int fac ( int n) {
int res = 1 ;
for ( int i = 1 ; i <= n; i++ ) res * = i;
return res;
}
void mother_fun ( ) {
for ( int i = 0 ; i <= num[ 1 ] ; i++ ) a[ i] = 1.0 / fac ( i) ;
for ( int cur = 2 ; cur <= n; cur++ ) {
memset ( b, 0 , sizeof ( b) ) ;
for ( int i = 0 ; i <= num[ cur] ; i++ ) {
for ( int k = 0 ; k + i <= m; k++ ) {
b[ i + k] + = a[ k] / fac ( i) ;
}
}
memcpy ( a, b, sizeof ( b) ) ;
}
printf ( "%.0lf\n" , a[ m] * fac ( m) ) ;
}
int main ( ) {
while ( scanf ( "%d%d" , & n, & m) != EOF ) {
memset ( a, 0 , sizeof ( a) ) ;
for ( int i = 1 ; i <= n; i++ ) scanf ( "%d" , num + i) ;
mother_fun ( ) ;
}
return 0 ;
}