HDU 1028 Ignatius and the Princess III:dp or 母函式

Leohh發表於2017-08-17

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=1028

題意:

  給你一個正整數n,將n拆分成若干個正整數之和,問你有多少種方案。

  注:"4 = 3 + 1"和"4 = 1 + 3"視為同一種方案。(加數是無序的)

 

題解1(dp):

  表示狀態:

    dp[n][m] = num of methods

    表示用均不超過m的元素組成n的方法數。

  

  如何轉移:

    假設當前狀態為dp[n][m].

    對於等於m的元素,有兩種決策。要麼不用,要麼用。

      (1)不用:dp[n][m] += dp[n][m-1]

      (2)用: dp[n][m] += dp[n-m][m]

    綜上:dp[n][m] = dp[n][m-1] + dp[n-m][m]

  

  找出答案:

    ans = dp[n][n]

  

  邊界條件:

    dp[0][i] = 1  (0<=i<=MAX_N)

 

 

題解2(母函式):

  要湊出n,每種方案無非是取幾個1,幾個2,幾個3......

  這就是母函式的經典問題啦(取硬幣)。

  

  構造母函式:

    G(x) = (1 + x^1 + x^2 + x^3...) * (1 + x^2 + x^4 + x^6...) * (1 + x^3 + x^6 + x^9...) * (1 + x^4 + x^8 + x^12...)...

  

  找出答案:

    x^n項的係數即為答案。

 

AC Code(dp):

 1 // dp[n][m] = num of methods
 2 // n: the elems are up to n
 3 // m: each elem won't be not more than m
 4 // dp[n][m] = dp[n][m-1] + dp[n-m][m]
 5 // ans = dp[n][n]
 6 // dp[0][m] = 1
 7 
 8 #include <iostream>
 9 #include <stdio.h>
10 #include <string.h>
11 #define MAX_N 125
12 
13 using namespace std;
14 
15 int n;
16 int dp[MAX_N][MAX_N];
17 
18 void cal_dp()
19 {
20     memset(dp,0,sizeof(dp));
21     for(int i=0;i<MAX_N;i++)
22     {
23         dp[0][i]=1;
24     }
25     for(int i=1;i<MAX_N;i++)
26     {
27         for(int j=1;j<MAX_N;j++)
28         {
29             if(i>=j) dp[i][j]=dp[i][j-1]+dp[i-j][j];
30             else dp[i][j]=dp[i][i];
31         }
32     }
33 }
34 
35 int main()
36 {
37     cal_dp();
38     while(cin>>n)
39     {
40         cout<<dp[n][n]<<endl;
41     }
42 }

 

AC Code(Generating Function):

 

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #define MAX_N 125
 5 
 6 using namespace std;
 7 
 8 int n;
 9 int ans[MAX_N];
10 int temp[MAX_N];
11 
12 void generating_function(int n)
13 {
14     memset(ans,0,sizeof(ans));
15     ans[0]=1;
16     for(int i=1;i<=n;i++)
17     {
18         memset(temp,0,sizeof(temp));
19         for(int j=0;j*i<=n;j++)
20         {
21             for(int k=0;k+j*i<=n;k++)
22             {
23                 temp[k+j*i]+=ans[k];
24             }
25         }
26         memcpy(ans,temp,sizeof(temp));
27     }
28 }
29 
30 int main()
31 {
32     generating_function(120);
33     while(cin>>n)
34     {
35         cout<<ans[n]<<endl;
36     }
37 }

 

相關文章