加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

topcoder srm531 div 1 300

(2012-02-01 19:11:19)
标签:

topcoder

srm531

div

1

300

it

分类: 动态规划
题目描述:
一共有n首歌曲,让你构造一个播放序列,序列有p首歌(p>=n,即序列中可以有重复的歌曲),序列中任何重复的歌曲之间必须至少有m首歌曲。
问你有多少种构造方式。
n 1~100
m 0~n
p n~100
解题报告:
dp[i][j]表示构造到序列中的第i首歌时,一共有j首不同的歌的构造方式。
那么dp[p][n]就是答案。
首先dp[1][1] = n
转移如下,有两步:
第一步:选择新歌,dp[i][j] += dp[i - 1][j - 1] * (n - (j - 1)); 由于dp[i - 1][j - 1]时已经有了j-1首歌,所以新歌可以选择的有 (n - (j - 1))种。
第二步:选择旧歌,那么j必须大于m,否则不可能,转移为:
dp[i][j] += dp[i - 1][j] * (j - m); 由于已经有了j首歌,而序列中第i首歌不能和前m首重复(易知,前m首之间不能有重复,或者说,序列中任意连续的m个都没有重复,所以,可以选择的有(j-m)种。
代码如下:
        long long dp[200][200];
        int numPlaylists(int N, int M, int P)
        {
            dp[1][1] = N;
            for(int i = 2; i <= P; i++)
                for(int j = 1; j <= min(i, N); j++)
                {
                    dp[i][j] = dp[i - 1][j - 1] * (N - j + 1);
                    if (j > M) dp[i][j] += dp[i - 1][j] * (j - M);
                    dp[i][j] %= mod;
                }
            return dp[P][N];
        }

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有