• C++
  • 信奥【下午2】---计数dp【整数划分】

  • @ 2024-4-27 15:42:35

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

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

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

输入格式

共一行,包含一个整数 n

输出格式

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

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

数据范围

1n1000

输入样例:

5

输出样例:

7

完全背包解法

状态表示: f[i][j]表示只从1~i中选,且总和等于j的方案数

状态转移方程: f[i][j] = f[i - 1][j] + f[i][j - i];

参考代码:

#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;
    for (int i = 1; i <= n; i ++ )
        for (int j = i; j <= n; j ++ )
            f[j] = (f[j] + f[j - i]) % mod;

    cout << f[n] << endl;

    return 0;
}

其他算法

状态表示: f[i][j]表示总和为i,总个数为j的方案数

状态转移方程: f[i][j] = f[i - 1][j - 1] + f[i - j][j];

实例代码:

#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[1][1] = 1;
    for (int i = 2; 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;

    return 0;
}

0 条评论

目前还没有评论...