SRM 531 DIV 2

600pt. NoRepeatPlaylist

dp[i][j] 表示構造到第i首歌時,用了j首不同的歌的排列組合數。

狀態轉移方程爲

dp[i][j]=dp[i-1][j-1]*(N-(j-1))+dp[i-1][j]*(j-M);

注:我們構造到第i首歌時,用了j種不同的歌,那麼在第i個位置。我們可以有兩種選擇。

(1)選擇新歌,前面i-1個位置用了j-1首不同的歌,那麼對於每個dp[i-1][j-1],在第i個位置我們還有

(N-(j-1))首不同的歌可以選擇。

(2)選擇舊歌,前面i-1個位置用了j首不同的歌,那麼緊靠第i個位置的前M個位置(i-M) 到

(i-1)  必須是不同的M首歌,j首之中佔了M首歌,那麼對於每個dp[i-1][j],在第i個位置,我們還有 (j-M)

首不同的歌可以選擇。

 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;

const int MOD = 1000000007;
long long dp[105][105];
//dp[i][j] 表示構造到第i首歌時,用了j首不同的歌的排列組合數
//狀態轉移方程爲 dp[i][j]=dp[i-1][j-1]*(N-(j-1))+dp[i-1][j]*(j-M);
class NoRepeatPlaylist
{
public:
   int numPlaylists(int N, int M, int P)
   {
	   memset(dp,0,sizeof(dp));
       dp[1][1]=N;
	   for(int i=2;i<=P;i++)
	   {
	      for(int j=1;j<=N && j<=i;j++)
		  {
		     dp[i][j]=dp[i-1][j-1]*(N-(j-1))%MOD;
             if(j-M>0)
				 dp[i][j]+=dp[i-1][j]*(j-M)%MOD;
		  }
	   }
	   return dp[P][N]%MOD;
   }
};


 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章