描述
小Hi的手机中存着N首他喜爱的歌曲。现在小Hi希望制作一个长度为L的播放列表,满足
-
每一首歌至少播放一编
-
同一首歌不能连续播放,之间至少间隔一首其他歌曲
请你计算一共有多少种不同的播放列表满足条件?由于结果可能非常大,你只需要输出结果模1000000009的余数。
输入
两个整数N和L。
对于30%的数据,1 ≤ N ≤ 5,N ≤ L ≤ 10
对于100%的数据,1 ≤ N ≤ 1000, N ≤ L ≤ 2000
输出
一个整数,代表答案。
样例输入
3 4
样例输出
18
分析
该题目初步分析需要用动态规划来实现。(泛类递推)
//代码实现以样例输入3 4为主
import java.Util.*;
//好的动态规划表
final int max_song_count = 3;
final int song_list_length = 4;
long[][] dp = new long[song_list_length + 1][max_song_count + 1]; // dp[i][j] 代表长度为i,歌曲数目有j曲的满足题目要求歌曲排列组合情况
for(int i = 0; i <= song_list_length; i++) {
Arrays.fill(dp[i], -1);
}
class Solution {
//通过getDp函数来递归的计算dp状态的值,使代码逻辑更清晰
public static long getDp(long[][] dp, int max_song_count, int length, int song_count) {
if(dp[length][song_count] != -1) { return dp[length][song_count]; }
if(length == 1) {
if(song_count == 1) {
dp[length][song_count] = max_song_count;
return dp[length][song_count];
}
return 0;
}
if(song_count == 1) {
if(length == 1) {
dp[length][song_count] = max_song_count;
return dp[length][song_count];
}
return 0;
}
//求解过程
dp[length][song_count] = 0;
dp[length][song_count] += getDp(dp, max_song_count, length - 1, song_count) * (song_count - 1);
dp[length][song_count] %= mod;
dp[length][song_count] += getDp(dp, max_song_count, length - 1, song_count - 1) * (max_song_count - (song_count - 1));
dp[length][song_count] %= mod;
return dp[length][song_count];
}
private static long mod = 1000000009;
}
//打印输出结果
System.out.println(Solution.getDp(dp, max_song_count, song_list_length, max_song_count))
18