(AcWing) 900. 整数划分 (计数DP)

一个正整数 n 可以表示成若干个正整数之和,形如:n=n1+n2+…+nk,其中 n1≥n2≥…≥nk,k≥1。

我们将这样的一种表示称为正整数 n 的一种划分。

现在给定一个正整数 n,请你求出 n 共有多少种不同的划分方法。

输入格式

共一行,包含一个整数 n。

输出格式

共一行,包含一个整数,表示总划分数量。

由于答案可能很大,输出结果请对 10^9+7 取模。

数据范围

1≤n≤1000

输入样例:

5

输出样例:

7

方法1:DP

 

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1010, mod = 1e9 + 7;

int n;
int f[N];

int main()
{
    cin >> n;

    f[0] = 1;
    //f[i]是从前i个物品中选取物品的 总体积<=背包总体积n的方法数
    //f[0]是体积为0的背包然后所有都不选是一种方案,
    //一个数都不选,总和是0,是一种方案f[i][0],前i个数中选,总和恰好等于0,只有一种都不选这种方案
    
    
    for (int i = 1; i <= n; i ++ )
        for (int j = i; j <= n; j ++ )
            f[j] = (f[j] + f[j - i]) % mod;
    //f[i][j] = f[i-1][j] + f[i][j-i]
    //          (不选i)    (选i)

    cout << f[n] << endl;

    return 0;
}

 方法2:

 

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1010, mod = 1e9 + 7;

int n;
int f[N][N];

int main()
{
    cin >> n;
    f[0][0] = 1;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=i;j++){
            f[i][j] = (f[i-1][j-1]+f[i-j][j])%mod;
        }
    }
    
    int res = 0;
    for(int i=1;i<=n;i++) res=(res+f[n][i])%mod;
    cout<<res<<endl;
}

 方法3:

#include <iostream>  
using namespace std;  
// Author: bjr  
//   
const int max = 1000;   
// sup是保存多项式的数组,sup[n]中的值代表xn的系数
// temp是临时多项式,保存相乘的临时中间情况  
int sup[max], temp[max];   
/*
程序始终只计算两个多项式之间的乘积,多个多项式的情况
先计算前两个的乘积,将结果作为第一个多项式,再与第三个相乘
依次类推,sup始终存放当前运算后的结果然后作为被乘多项式,
*/  
int main()  
{   
    int target;   //  目标重量, 比如上面的例子里就是10,要<max的值
    int i, j, k;  
   
    while(cin >> target)  
    {  
        for(i=0; i<=target; ++i)     
        {  
            sup[i] = 1;   
//初始化第一个多项式,也就是用1g砝码的多项式,
//注意如果题目没给1g的砝码那么就不能++i,而要加上砝码的质量
            temp[i] = 0;  
//将临时区清空,无论第一个多项式质量是几都要全部置零
        }  
        for(i=2; i<=target; ++i)   
// 生成后续的第i个多项式,此题中是2g,i从2开始。
//如果砝码的值不是规律增长,i可能需要取决于输入
        {  
   
            for(j=0; j<=target; ++j)   
// 遍历当前结果多项式的每一项(当前结果的第j项)与第i个多项式相乘,
                for(k=0; k+j<=target; k+=i) 
// 遍历第i个多项式的每一项,此处构造用小砝码组成大砝码的多项式
                {  
                    temp[j+k] += sup[j];  
//幂运算,注意理解
                }  
            for(j=0; j<=target; ++j)    
// 将临时的结果覆盖当前结果,同时把临时结果置零,为下次做准备
            {  
                sup[j] = temp[j];  
                temp[j] = 0;  
            }  
        }  
        cout << sup[target] << endl;  //输出结果
    }  
    return 0;  
}  

 转载于:普通母函数的原理及实现_太上绝情的博客-CSDN博客

猜你喜欢

转载自blog.csdn.net/GF0919/article/details/132428187
今日推荐