LeetCode每日一题(920. Number of Music Playlists)

Your music player contains n different songs. You want to listen to goal songs (not necessarily different) during your trip. To avoid boredom, you will create a playlist so that:

Every song is played at least once.
A song can only be played again only if k other songs have been played.
Given n, goal, and k, return the number of possible playlists that you can create. Since the answer can be very large, return it modulo 109 + 7.

Example 1:

Input: n = 3, goal = 3, k = 1
Output: 6

Explanation: There are 6 possible playlists: [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], and [3, 2, 1].

Example 2:

Input: n = 2, goal = 3, k = 0
Output: 6

Explanation: There are 6 possible playlists: [1, 1, 2], [1, 2, 1], [2, 1, 1], [2, 2, 1], [2, 1, 2], and [1, 2, 2].

Example 3:

Input: n = 2, goal = 3, k = 1
Output: 2
Explanation: There are 2 possible playlists: [1, 2, 1] and [2, 1, 2].

Constraints:

  • 0 <= k < n <= goal <= 100

抄的官方的答案。
dp[l][n]是 l 首歌的歌单, n 首歌的排列组合数量, 那 dp[l][n]是由两部分组合起来的, 一部分是 dp[l-1][n-1]外加一首 n-1 之外的新歌, 另一部分是 dp[l-1][n]外加 n 当中的一首歌的重复, 第一种情况我们可以在 n-1 之外选择任意一首歌加到歌单中, 所以可选歌的数量是 total-(n-1), 第二种情况我们要判断前面是否已经播放了 k 首不同的歌, 所以我们要比较 n 和 k 的大小, 只有 n > k 的时候我们才能将这种情况下的排列组合数量加到答案中。


impl Solution {
    pub fn num_music_playlists(n: i32, goal: i32, k: i32) -> i32 {
        let mut dp = vec![vec![0; n as usize + 1]; goal as usize + 1];
        dp[0][0] = 1;
        for i in 1..=goal {
            for j in 1..=n {
                dp[i as usize][j as usize] +=
                    dp[i as usize - 1][j as usize - 1] * (n - j + 1) as i64;
                dp[i as usize][j as usize] +=
                    dp[i as usize - 1][j as usize] * (j - k).max(0) as i64;
                dp[i as usize][j as usize] %= 1000000007;
            }
        }
        dp[goal as usize][n as usize] as i32
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值