As Gerald, Alexander, Sergey and Gennady are already busy with the usual New Year chores, Edward hastily decorates the New Year Tree. And any decent New Year Tree must be decorated with a good garland. Edward has lamps of m colors and he wants to make a garland from them. That garland should represent a sequence whose length equals L. Edward’s tree is n layers high and Edward plans to hang the garland so as to decorate the first layer with the first l1 lamps, the second layer — with the next l2 lamps and so on. The last n-th layer should be decorated with the last ln lamps,
Edward adores all sorts of math puzzles, so he suddenly wondered: how many different ways to assemble the garland are there given that the both following two conditions are met:
Help Edward find the answer to this nagging problem or else he won’t manage to decorate the Tree by New Year. You may consider that Edward has an unlimited number of lamps of each of m colors and it is not obligatory to use all m colors. The garlands are considered different if they differ in at least one position when represented as sequences. Calculate the answer modulo p.
The first line contains three integers n, m and p (1 ≤ n, m ≤ 106, 2 ≤ p ≤ 109) which are the number of the tree’s layers, the number of the lamps’ colors and module correspondingly. The next line contains n integers li (1 ≤ li ≤ 5000, ).
Print the only integer — the number of garlands modulo p.
3 2 1000
3 1 2
8
2 3 1000
2 2
24
1 1 1000
5
0
In the first sample the following variants are possible: 121|1|12, 121|1|21, 121|2|12, 121|2|21, 212|1|12, 212|1|21, 212|2|12, 212|2|21. In the second sample the following variants are possible: 12|13, 12|23, 12|31, 12|32 and so on.
题目大意:
圣诞树上挂彩球。
要求从上到下挂n行彩球。
已知有m种颜色的球,球的数量不限。
要求结果对p取模。
之后n个数,表示第 i 根绳长 li ,也就是要挂 li 个球。
要求每根绳上相邻彩球颜色不同。
相邻的绳子上挂的彩球种类不能相同。
彩球种类不相同是指至少有一种颜色 相邻两根绳子不共用。
考虑 dp[i][j] 表示在第 1 到 i−1 根绳子排列合法的情况下,第 i 根绳子用 j 种小球的合法方案数。
那么 dp[i][j]=∑k=1mdp[i−1][k]∗(i绳子上放j种小球的合法方案)−(i与i−1绳子用同样小球的方案数)
这里用容斥是因为求和那一步可以直接在遍历 i−1 的过程中得到。
同时注意减去的是用同种小球,而不是同数量。减去的是 i 与 i−1 用完全相同的小球的方案数。
首先解决i绳子上放j种小球。
其实求的是 a[i][j] —长为i的绳子上放j种小球的方案数(两两不相邻)
这里我们让 a[i][j]∗Ajk 为上述结果(k为可选颜色数量)
为什么要这样搞?因为这样这个数组在容斥那里也就可以用上了。
i与i-1绳子用同样小球的方案数 其实就是 dp[i−1][j]∗a[i][j]∗Ajj
因为此时 i−1绳子上的小球种类已经选定了
那么a数组怎么搞?其实就是第二类斯特林数。很耳熟吧?或者你已经知道怎么做了,。
不过是种变形。
a[i][j]=dp[i−1][j]∗(j−1)+dp[i−1][j−1]
考虑的其实就是j种小球往i个无编号的盒子里放,每个盒子放一个,相邻盒子小球不一样。
dp[i−1][j−1] 表示 i−1 个盒子放 j−1 种小球,变成i盒子j小球,自然新增一小球一盒子并相匹配。
此外 dp[i−1][j] 表示 i−1 个盒子 j 种小球,新增一个盒子时可以放除了相邻盒子中的小球外任意小球,即 (j−1) 个。
然后 Ajm 和 Ajj 预处理出来就行。
搞这么麻烦其实就是为了省去除法。因为可能对任何数取模,逆元不好弄。
代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define pr pair
#define fread(ch) freopen(ch,"r",stdin)
#define fwrite(ch) freopen(ch,"w",stdout)
using namespace std;
const int inf = 0x3f3f3f3f;
const int msz = 10000;
const double eps = 1e-8;
int mod;
ll xx[5555],c[5555];
ll a[5555][5555];
ll dp[2][5555];
void init(int m)
{
a[0][0] = 1;
for(int i = 1; i <= 5000; ++i)
for(int j = 1; j <= min(m,i); ++j)
{
a[i][j] = ((((a[i-1][j]*(j-1))%mod)+a[i-1][j-1])%mod);
}
xx[1] = m;
for(int i = 2; i <= min(m,5000); ++i)
xx[i] = (xx[i-1]*(m-i+1))%mod;
c[1] = 1;
for(int i = 2; i <= min(m,5000); ++i)
c[i] = (c[i-1]*i)%mod;
}
int main()
{
//fread("");
//fwrite("");
int n,m;
scanf("%d%d%d",&n,&m,&mod);
init(m);
int l;
int pos = 0;
ll sum,tmp;
for(int s = 0; s < n; ++s)
{
scanf("%d",&l);
tmp = 0;
memset(dp[pos^1],0,sizeof(dp[pos^1]));
if(s == 0)
{
for(int i = 1; i <= min(m,l); ++i)
{
dp[pos^1][i] = (xx[i]*a[l][i])%mod;
tmp = (tmp+dp[pos^1][i])%mod;
}
}
else
{
for(int i = 1; i <= min(m,l); ++i)
{
dp[pos^1][i] = (((((((xx[i]*sum)%mod)-((c[i]*dp[pos][i])%mod))%mod)+mod)%mod)*a[l][i])%mod;
tmp = (tmp+dp[pos^1][i])%mod;
}
}
sum = tmp;
pos ^= 1;
}
printf("%lld\n",sum);
return 0;
}