母函數及其應用+模板


部分摘自這位大佬的博客https://www.cnblogs.com/linyujun/p/5207730.html

生成函數即母函數,是組合數學中尤其是計數方面的一個重要理論和工具。 最早提出母函數的人是法國數學家LaplaceP.S.在其1812年出版的《概率的分析理論》中明確提出“生成函數的計算”。 生成函數的應用簡單來說在於研究未知(通項)數列規律,用這種方法在給出遞推式的情況下求出數列的通項。 

在這里我們不去高深地研究數學上母函數,而是講講簡單的母函數應用。

1.母函數引入

就是把一個已知的序列和x的多項式合並起來,新產生的多項式就叫原來序列的母函數

序列{0,1,2,3,4,5...n}的母函數就是

f(x)=0+x+2x^2+3x^3+4x^4+...+nx^n(這個x沒有任何意義,應該說,你不需要把它當做一個函數,你只要知道母函數這么寫就可以了)

 

序列{1,1,1,1,1......}的母函數就是

f(x)=1+x+x^2+x^3+x^4....

 

二項式展開的序列比如這個{1,4,6,4,1,0,0,0,0,0.....}是C(4,0)到C(4,4)的系數,那它的母函數就是

f(x)=1+4x+6x^2+4x^3+1x^4

 

這些東西對於我們來說並沒有說明意義,母函數對我們來說只是一個工具,是一個載體,那來看看母函數是怎么樣裝載數據的吧!

 

例1:若有1克、2克、3克、4克的砝碼各一 枚,能稱出哪幾種重量?各有幾種可能方案? 

 假如x的指數表示砝碼

那么

1克的砝碼表示為1+x^1

2克的砝碼表示為1+x^2

3克的砝碼表示為1+x^3

4克的砝碼表示為1+x^4

 

每個砝碼都可以選擇取或不取

所以這里的1可以認為1*x^0,表示不取這顆砝碼

 那么把這些乘起來

(1+x^1)(1+x^2)(1+x^3)(1+x^4)

=1+(x^1)+(x^2)+2(x^3)+2(x^4)+2(x^5)+2(x^6)+2(x^7)+(x^8)+(x^9)+(x^10)

 

根據指數來看,我們可以稱出0~10這么多的重量,其中3~7的系數為2,說明有2種稱的方法

那么我們來細看一遍

0:(什么砝碼都不放).......................(1種)

1:1.............................................(1種)

2:2.............................................(1種)

3:3或1+2.....................................(2種)

4:4或1+3.....................................(2種)

5:1+4或2+3.................................(2種)

6:2+4或1+2+3..............................(2種)

7:3+4或1+2+4..............................(2種)

8:1+3+4......................................(1種)

9:2+3+4......................................(1種)

10:1+2+3+4.................................(1種)

 

分毫不差

所以說母函數在ACM就是這么用的,跟函數沒關系,跟寫法有關系。

 

例2:求用1分、2分、3分的郵票貼出不同數值的方案數,每種郵票可以有無限張。

因郵票允許重復,故母函數為:

對於這種連續相乘,我們人類是很討厭的,但對於計算機這種重復運算是很輕松的,我們只要將我們解多項式的思路帶進去即可。

2.代碼說明

我們首先知道對於最后得到的那一個母函數,系數代表的是方案數,而指數代表的是組成的數值,運算過程就是多項式的乘法。而兩個多次方程的乘法,運算無非是系數相乘,指數相加,僅僅是這個方程的兩個信息的運算。那能不能用什么數據結構直接表示出一個對象的這個兩個信息呢?首先想到的可能是結構體,結構體可以用來表示一個對象的多個信息,但是運算繁瑣;其實用數組就可以了,下標代表組成的數值,數組取值代表方案數!!!

a.求用1分、2分、3分的郵票貼出不同數值的方案數:(每張郵票的數量是無限的)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define MAX 310
 6 int a[MAX];///最終合並的多項式
 7 int b[MAX];///臨時合並用的多項式
 8 int n;
 9 const int N=110;
10 using namespace std;
11 void init()
12 {
13     int i,j,k;
14     a[0]=1;///一開始的0的情況
15     for (i=1; i<=3; i++)///代表1分,2分,3分三個多項式的合並
16     {
17         for (j=0; j<N; j+=i)///i分的郵票,步長為i
18         {
19             for (k=0; k+j<N; k++)///從x^0到x^N遍歷一遍
20             {
21                 b[j+k]+=a[j];///核心
22             }
23         }
24         for (j=0; j<N; j++)///b中數據抄到a,b清空
25         {
26             a[j]=b[j];
27             b[j]=0;
28         }
29     }
30 }
31 int main()
32 {
33     int i,j,k;
34     init();
35     while(scanf("%d",&n)!=EOF)
36     {
37         printf("%d\n",a[n]);
38     }
39     return 0;
40 }

 

b.hdu 1028

http://acm.hdu.edu.cn/showproblem.php?pid=1028

題目問一個數字n能夠拆成多少種數字的和

比如n=4

  4 = 4;
  4 = 3 + 1;
  4 = 2 + 2;
  4 = 2 + 1 + 1;
  4 = 1 + 1 + 1 + 1;

有5種,那么答案就是5

其實這個題就可以轉換成使用1~N個數,每個數可以多次使用,能組成的數有多少種方案?

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define MAX 130
 6 #define N 130
 7 #define ll long long int
 8 ll a[MAX];
 9 ll b[MAX];
10 int n;
11 using namespace std;
12 void init()
13 {
14     int i,j,k;
15     a[0]=1;
16     for (i=1; i<=MAX; i++)
17     {
18         for (j=0; j<N; j+=i)
19         {
20             for (k=0; k+j<N; k++)
21             {
22                 b[j+k]+=a[k];
23             }
24         }
25         for (j=0; j<N; j++)
26         {
27             a[j]=b[j];
28             b[j]=0;
29         }
30     }
31 }
32 int main()
33 {
34     init();
35     while(scanf("%d",&n)!=EOF)
36     {
37         printf("%lld\n",a[n]);
38     }
39     return 0;
40 }
View Code

 

c.hdu 1398

http://acm.hdu.edu.cn/showproblem.php?pid=1398

題目說一個國家的硬幣都是方形的,面值也是方形的

有1塊錢,4塊錢,9塊錢,16塊錢......一直到289塊錢(17^2)

問想組成n塊錢有幾種方法

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define ll long long int
 6 #define MAX 17
 7 #define N 305
 8 using namespace std;
 9 ll a[N];
10 ll b[N];
11 void init()
12 {
13     int i,j,k;
14     a[0]=1;
15     for (i=1; i<=MAX; i++)
16     {
17         for (j=0; j<N; j+=i*i)
18         {
19             for (k=0; k+j<N; k++)
20             {
21                 b[j+k]+=a[k];
22             }
23         }
24         for (j=0; j<N; j++)
25         {
26             a[j]=b[j];
27             b[j]=0;
28         }
29     }
30 }
31 int main()
32 {
33     int n;
34     init();
35     while(scanf("%d",&n)!=EOF)
36     {
37         if(n==0)
38         {
39             break;
40         }
41         printf("%lld\n",a[n]);
42     }
43     return 0;
44 }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM