整数划分

方法1:完全背包法

1.状态定义:
f[i][j]: 表示只从1 ~ i中选,且总体积恰好为j的方案数

#include <bits/stdc++.h>
using namespace std;

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

int n;
int f[N]; 

//状态定义: f[i][j] : 只从 1 ~ i 中选,且总体积恰好j的集合的数量

int main()
{
    scanf("%d",&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;
        }
    }
    printf("%d",f[n]);
    
    return 0;
}

第二种方法

1.状态定义:

f[i][j] : 总和为 i, 分成 j 个数的方案

2.状态计算:最小值为1的情况和,最小值大于1的情况

最小值为1的情况 :

说明每个方案都存在1,先去掉1,合为 i - 1,分成 j - 1个数的和的方案

最小值大于1的情况:

所有总和为 i,表示的时j个数的和,并且每一个数都严格大于1,因此对每一个数都先减去 1

j个数每一个书都减去1,总和为i - j的就 j个数的和

最后需要每个数的方案数累加

#include <bits/stdc++.h>
using namespace std;

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

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

int main(){
    
    scanf("%d",&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;
    }
    printf("%d",res);
    return 0;
}
posted @ 2024-09-09 21:36  LTphy  阅读(27)  评论(0)    收藏  举报