给定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);
}
};