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

题目链接: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 }

 

posted @ 2017-08-17 23:55  Leohh  阅读(202)  评论(0编辑  收藏  举报