生成函數
定義
生成函數又叫母函數,可以看成對代數對象的形式上的處理,利用代數方法計算計數問題,另外也是無限可微函數的冪級數展開式。分為普通生成函數和指數生成函數。
普通生成函數
序列\(h\)的普通生成函數(ordinary generating function,OGF)定義為形式冪級數:
\(h\)既可以是有窮序列,也可以是無窮序列。
例:牛頓二項式定理
設\(\alpha\)為實數,二項式系數的無窮數列
的生成函數是
封閉形式
\(1,1,1,1\cdots\)的生成函數為\(F(x)=\sum_{i \ge 0} x^i\),可以轉化為
同理,等比數列\(1,p,p^2,p^3,\cdots\)可以表示為\(\frac{1}{1-px}\)。
指數生成函數
序列\(h\)的指數生成函數(exponential generating function,EGF)定義為形式冪級數:
\(h\)既可以是有窮序列,也可以是無窮序列。
\(h\)的指數生成函數也可以看成\(\{\hat{h}|\hat{h_i} = \frac{h_i}{i!}\}\)的普通生成函數。
例:\(e^x\)
\(1,1,1,1\cdots\)的指數生成函數為
一般地,\(1,a,a^2,a^3,\cdots\)的指數生成函數是
用途
普通生成函數——組合
設\(h_i\)表示
的非負整數解的個數。根據插板法有
\(h\)的生成函數是
我們可以理解成是k個\(\frac{1}{1-x}\)乘在一起,也就是
例:[HDU2152 Fruit][https://vjudge.net/problem/HDU-2152]
答案為
中\(x^m\)系數。
#include <bits/stdc++.h>
using namespace std;
const int mn=206;
int n,m,a,b,p[mn],q[mn];
int main()
{
while(scanf("%d%d",&n,&m)!=EOF) {
for(int i=0;i<=m;++i) p[i]=0;
p[0]=1;
for(int i=1;i<=n;++i) {
scanf("%d%d",&a,&b);
for(int j=0;j<=m;++j) q[j]=0;
for(int j=a;j<=b;++j)
for(int k=m-j;k>=0;--k) {
q[j+k]+=p[k];
}
for(int j=0;j<=m;++j) p[j]=q[j];
}
printf("%d\n",p[m]);
}
return 0;
}
指數生成函數——排列
考慮\(n\)個元素的\(k\)排列的指數生成函數
其中\(P(n,i) = \frac{n!}{(n-i)!}\)。我們可以發現
是組合數的普通生成函數。
多重集的\(k\)排列
設多重集\(S\)為\(\{n_1a_1,n_2a_2,\cdots,n_ka_k\}\),那么其排列為
例:[poj3734 Blocks][http://poj.org/problem?id=3734]
推出式子是
#include <cstdio>
#define LL long long
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define fi first
#define se second
#define lc nd<<1
#define rc nd<<1|1
#define lowbit(x) (x&(-x))
#define pLL pair<LL,LL>
using namespace std;
const int mod=10007;
template<typename T>
T qpow(T a,T b) {LL ans=1;while(b) {if(b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;}return ans;}
const int mn=1e5+6;
int main()
{
int tests=1;scanf("%d",&tests);
while(tests--) {
int n;
scanf("%d",&n);
printf("%lld\n",1ll*(qpow(4,n)+qpow(2,n+1))*qpow(4,mod-2)%mod);
}
return 0;
}