AcWing900.整数划分(python)

发布时间 2023-05-22 15:40:24作者: JaineCC

题目详情

知识点

计数类DP

分析题目,k个数是默认排好序的,也就是说,对于划分我们的考虑是无序的:例如

4 = 1+1+2

4 = 1+2+1

4 = 2+1+1

以上三种方式是没有区别的,所以在求解方案数的过程中是不用考虑数之间的顺序的【无序的】

我们不考虑顺序,转化成背包:容量为n的背包,有1~n体积的物体,每种有无限个【完全背包】

我们要求恰好装满这个容积为n的背包的方案数:因为不考虑顺序所以每一种背包的选法都对应一种数字的划分方式【一一对应】

f[i][j]表示从1到i中选,体积恰好为j的选法的数量

二维DP代码【超时】

mod = int(1e9+7)
n = int(input())
dp = [[0 for _ in range(n+1)]for _ in range(n+1)]
for i in range(n+1): dp[i][0] = 1 # 初始化:都不选,组成0
for i in range(1,n+1):
    for j in range(1,n+1):
        for s in range(n+1):
            if 0 <= j-s*i <= n:
                dp[i][j] = (dp[i][j] + dp[i-1][j-s*i])%mod
print(dp[n][n]%mod)

用c好像可以过,但是python会超时,注意初始化的部分!

优化

惊奇的发现他们后面完全一样

所以f[i][j]=f[i-1][j]+f[i][j-i]

然后再优化到一维

一维DP代码

mod = int(1e9+7)
n = int(input())
dp = [0 for _ in range(n+1)]
for i in range(n+1): dp[0] = 1 
for i in range(1,n+1):
    for j in range(i,n+1):
        dp[j] = (dp[j] + dp[j-i])%mod
print(dp[n]%mod)