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;
   }
};


 

 

 

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