通常來說,母函數的思想就是使用冪級數來表示一個離散數列。例如對於一個數列是a={a0,a1,a2,-------ak},那麼我們可以母函數的定義就是G(x)=a0+a1*x+a2*x^2+a3*x^3------an*x^n,這裡的G(x)就是數列a的母函數。
母函數可以用來解決整數拆分問題,下面舉一個例子來說明。
例如我們有重量為1克、2克、3克、4克的砝碼各一個,那麼問你這些砝碼可以稱出幾中重量?每一種重量有多少種方案數?
對於這個問題我們可以這樣定義母函數G(x)=(1+x)*(1+x^2)*(1+x^3)*(1+x^4),那麼這個時候我們把G(x)展開之後得到一個多項式,這個時候的指數就是可以稱出的重量,對應的該指數的係數就是該重量對應的稱出的方案數,自己展開看看就知道了。
下面我們說說HDU 1284 的“錢幣兌換問題”吧,題目的意思就是說給你三種面值的幣分別是1分、2分、3分,那麼問你一個錢數n有幾種方案可以拼湊得到這個錢數n?
這道題還是比較好看的,我們根據母函數的定義,以及多項式的每一項和係數所表示的含義,我們可以定義母函數G(x)=(1+x+x^2+x^3--------)*(1+x^2+x^4+x^6+x^8--------)*(1+x^3+x^6+x^9--------------),那麼我們使用母函數的額展開式對應的指數就是能表示的錢幣數,係數就是表示該錢幣數的方案數。
所以問題就是求出對應的n的係數就可以了,這個比較簡單,就是類比手工多項式的展開,下面附上我的AC代碼供參考:
#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>using namespace std;const int Max=32769;int ans[Max];int tans[Max];int main(){ int i,j,n; for(int i=0;i<Max;i++) ans[i]=1; memset(tans,0,sizeof(tans)); for(int k=2;k<=3;k++) { for(i=0;i<Max;i++) { for(j=0;i+j<Max;j+=k) { tans[i+j]+=ans[i]; } } for(i=0;i<Max;i++) { ans[i]=tans[i]; tans[i]=0; } } while(scanf("%d",&n)!=EOF) { printf("%d\n",ans[n]); } return 0;}