有两个要素提示,一个是有n个物品,一个是有gaol个长度,dp[n][goal],就是总共有多少字种排列结果,状态转移有两部分,dp[i][j] = dp[i-1][j-1] * (n - (j-1)) + dp[i-1][j]* max(j-k,0)。前一部分代表,在有j-1个物品来组成,长度为i-1的list基础上,多给一个新的物品,会有多少种呢?这取决于新的物品的可选数量,目前用了j-1个,还有n-(j-1)个新物品,所以一共有dp[i-1][j-1] * (n - (j-1)) 种新的选择。而如果目前已经用了j个,但是组成的list长度只有i-1,那需要复用一个物品,根据重复条件,需要有k个其他物品被使用了,那如果j - k < 0,说明没法重复,如果>0,说明可以被复用的物品有j-k个,也就有j-k种方式。注意dp[0][0]的初始值。
class Solution:
def numMusicPlaylists(self, n: int, goal: int, k: int) -> int:
Mod = 10**9 + 7
dp = [[0 for _ in range(n+1)] for _ in range(goal+1)]
dp[0][0] = 1
for i in range(1, goal+1):
for j in range(1,min(i, n)+1):
dp[i][j] = dp[i-1][j-1]*(n-j+1) + dp[i-1][j]*max((j-k),0)
return dp[-1][-1]%Mod