(一)普通母函數(shù):##
http://www.wutianqi.com/?p=596
#include <iostream>
using namespace std;
// Author: Tanky Woo
// www.wutianqi.com
const int _max = 10001;
// c1是保存各項質(zhì)量砝碼可以組合的數(shù)目
// c2是中間量,保存沒一次的情況
int c1[_max], c2[_max];
int main()
{ //int n,i,j,k;
int nNum; //
int i, j, k;
while(cin >> nNum)
{
for(i=0; i<=nNum; ++i) // ---- ①
{
c1[i] = 1;
c2[i] = 0;
}
for(i=2; i<=nNum; ++i) // ----- ②
{
for(j=0; j<=nNum; ++j) // ----- ③
for(k=0; k+j<=nNum; k+=i) // ---- ④
{
c2[j+k] += c1[j];
}
for(j=0; j<=nNum; ++j) // ---- ⑤
{
c1[j] = c2[j];
c2[j] = 0;
}
}
cout << c1[nNum] << endl;
}
return 0;
}
① 、首先對c1初始化,由第一個表達(dá)式(1+x+x2+..xn)初始化,把質(zhì)量從0到n的所有系數(shù)都初始化為1.
② 、 i從2到n遍歷,這里i就是指第i個表達(dá)式,上面給出的第二種母函數(shù)關(guān)系式里,每一個括號括起來的就是一個表達(dá)式。
③、j 從0到n遍歷,這里j就是(前面i個表達(dá)式累乘的表達(dá)式)里第j個變量,(這里感謝一下seagg朋友給我指出的錯誤,大家可以看下留言處的討論)。如(1+x)(1+x2)(1+x3),j先指示的是1和x的系數(shù),i=2執(zhí)行完之后變?yōu)椋?+x+x2+x3)(1+x^3),這時候j應(yīng)該指示的是合并后的第一個括號的四個變量的系數(shù)。
④ 第j個指數(shù)的冪可以增加的數(shù)為k,k每次增i。( 因為第i個表達(dá)式的增量是i:(1+xi+x2i+...+x^ni+...) )。
⑤ 、把c2的值賦給c1,而把c2初始化為0,因為c2每次是從一個表達(dá)式中開始的。
https://vjudge.net/problem/HDU-1028
#include <cstdio>
using namespace std;
const int maxn= 125;
// c1是保存各項質(zhì)量砝碼可以組合的數(shù)目
// c2是中間量,保存每一次的情況
int c1[maxn], c2[maxn];
int main()
{ int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<=n;i++)
{
c1[i]=1;
c2[i]=0;
}
for(int i=2;i<=n;i++)
{
for(int j=0;j<=n;j++)
{
for(int k=0;k+j<=n;k+=i)
{
c2[j+k]+=c1[j];
}
}
for(int j=0;j<=n;j++)
{
c1[j]=c2[j];
c2[j]=0;
}
}
printf("%d\n",c1[n]);
}
return 0;
}
(二)指數(shù)母函數(shù)##
指數(shù)型母函數(shù)主要是關(guān)于排列組合方面的問題。
分別看兩個比較典型的問題對比:
普通母函數(shù)問題:有紅球兩個,白球、黃球各一個,試求有多少種不同的組合方案。
指數(shù)型母函數(shù)問題:假設(shè)有8個元素,其中a1重復(fù)3次,a2重復(fù)2次,a3重復(fù)3次。從中取r個元素,求其排列數(shù)。
下面是指數(shù)型母函數(shù)的定義:

對于上面的問題“假設(shè)有8個元素,其中a1重復(fù)3次,a2重復(fù)2次,a3重復(fù)3次。從中取r個組合,求其組合數(shù)?!保?br> (感謝 3Dnn 同學(xué)指出,下圖的 28/3! 應(yīng)該改為 26/3!)

https://vjudge.net/problem/HDU-1521
題意:有n種物品,并且知道每種物品的數(shù)量。要求從中選出m件物品的排列數(shù)。例如有兩種物品A,B,并且數(shù)量都是1,從中選2件物品,則排列有"AB","BA"兩種。
#include <cstdio>
#include<string.h>
using namespace std;
const int maxn=11;
double c1[maxn],c2[maxn];
int factor[maxn];
int num[maxn];
int main()
{
factor[0]=1;
for(int i=1;i<=10;i++)
factor[i]=factor[i-1]*i;
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%d",num+i);
memset(c1,0,sizeof(c1));
memset(c2,0,sizeof(c2));
for(int i=0;i<=num[1];i++)
{
c1[i]=1.0/factor[i];
}
for(int i=2;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
for(int k=0;j+k<=m&&k<=num[i];k++)
{
c2[j+k]+=c1[j]/factor[k];
}
}
for(int j=0;j<=m;j++)
{
c1[j]=c2[j];
c2[j]=0;
}
}
printf("%.f\n",c1[m]*factor[m]);
}
return 0;
}
