SRM531 D1 L1

Problem Statement

给定N个数,要求选出P个数(可以重复),使得每个数至少出现一次,且重复出现的数之间至少间隔M个数,问说有多少种可能。

参考解题报告,可以用动态规划的方法来做,基于这样的一个观察,连续的M+1个数肯定是两两不同的,所以可以一个一个选,还没选过的数可以直接选进去,还有就是除了那M个不同的数以外,任选一个数进来,可以保证两两不同。

同时可以用容斥原理来做,先忽略掉每个数至少出现一次这个条件,可以结合之前的那个观察,得出一个结果,具体参加这里

#include <iostream>
#include <string>
#include <vector>
using namespace std;

typedef long long int64;

const int MOD = 1000000007;
const int MAX = 105;

int f[MAX][MAX][MAX];

class NoRepeatPlaylist
{
public:
int n, m, p;
int go(int cnt, int x, int y)
{
if(cnt == p) return y == 0 ? 1 : 0;

if(f[cnt][x][y] != -1) return f[cnt][x][y];

int64 res = 0;

if(y > 0) res += (int64)y * go(cnt + 1, x + 1, y - 1);
if(x > m) res += (int64)(x - m) * go(cnt + 1, x, y);

f[cnt][x][y] = res % MOD;

return res % MOD;
}
int numPlaylists(int N, int M, int P)
{
n = N;
m = M;
p = P;

memset(f, -1, sizeof(f));
return go(0, 0, n);
}
};



你可能感兴趣的:(rm)