【完全背包/母函数/递推】HDU1028-Ignatius and the Princess III

来源:互联网 发布:网络通信 语法 编辑:程序博客网 时间:2024/06/05 09:17

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1028

Problem Description
"Well, it seems the first problem is too easy. I will let you know how foolish you are later." feng5166 says.

"The second problem is, given an positive integer N, we define an equation like this:
  N=a[1]+a[2]+a[3]+...+a[m];
  a[i]>0,1<=m<=N;
My question is how many different equations you can find for a given N.
For example, assume N is 4, we can find:
  4 = 4;
  4 = 3 + 1;
  4 = 2 + 2;
  4 = 2 + 1 + 1;
  4 = 1 + 1 + 1 + 1;
so the result is 5 when N is 4. Note that "4 = 3 + 1" and "4 = 1 + 3" is the same in this problem. Now, you do it!"
 

Input
The input contains several test cases. Each test case contains a positive integer N(1<=N<=120) which is mentioned above. The input is terminated by the end of file.
 

Output
For each test case, you have to output a line contains an integer P which indicate the different equations you have found.
 

Sample Input
41020
 

Sample Output
542627

完全背包代码:

#include<iostream>#include<cstring>using namespace std;const int maxn=120;int dp[maxn];//  完全背包求方案数;void CompletePack(){    memset(dp,0,sizeof(dp));    dp[0]=1;        //  初始化    for(int i=1;i<=maxn;i++){       //  填数字i;        for(int j=i;j<=maxn;j++){   //  容量为j的方案数更新;            dp[j]+=dp[j-i];        }    }}int main(){    int n;    cin.sync_with_stdio(false);    CompletePack();    while(cin>>n){        cout<<dp[n]<<endl;    }    return 0;}

母函数代码:

#include<iostream>using namespace std;//  母函数const int maxn=120;int f[maxn]={0};        //  保存对应指数的系数(方案数)int tmp[maxn]={0};      //  临时保存分解一个因式的对应指数的系数void faction(int N){    for(int i=0;i<=N;i++)        f[i]=1;     //  第一个数,所构成的方案数都是1;    for(int i=2;i<=N;i++){      //  从第二个表达式开始        //  因式逐个分解;        for(int j=0;j<=N;j++)  //  表达式内从第一个开始(j表示的是指数);            for(int k=0;k+j<=N;k+=i)   //  表达式指数增加值;                tmp[j+k]+=f[j]; //  表示指数为j+k的系数;        //  更新指数系数;        for(int j=0;j<=N;j++){            f[j]=tmp[j];            tmp[j]=0;        }    }}int main(){    int n;    cin.sync_with_stdio(false);    faction(maxn);    while(cin>>n){        cout<<f[n]<<endl;    }    return 0;}

递推代码:

#include<iostream>using namespace std;const int maxn=121;int f[maxn][maxn]={0};  //  f[i][j]表示组合成i值且组合数中最小数为j的方案数;void faction(int N){    for(int i=0;i<N;i++)        f[0][i]=1;    for(int i=1;i<N;i++){       //  所有可以组成的值;        for(int j=1;j<=i;j++){  //  所组成的值的可能存在的数字;            for(int k=j;k<=i;k++){  //  添加一个数字k,将更新方案数;                f[i][j]+=f[i-k][k]; //  组合值为i-k,切最小数为k的方案数直接加上一个k就构成了新的组合值为i的方案;            }        }    }}int main(){    faction(maxn);    cin.sync_with_stdio(false);    int n;    while(cin>>n){        cout<<f[n][1]<<endl;    }    return 0;}

0 0
原创粉丝点击