生成函数
定义
生成函数又叫母函数,可以看成对代数对象的形式上的处理,利用代数方法计算计数问题,另外也是无限可微函数的幂级数展开式。分为普通生成函数和指数生成函数。
普通生成函数
序列\(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;
}