【第二类斯特林数+容斥原理】Codeforces-140E. New Year Garland
作者:互联网
题目链接(https://codeforces.com/problemset/problem/140/E)
E. New Year Garland
time limit per test 5 seconds
memory limit per test 256 megabytes
input standard input
output standard output
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 \(l_1\) lamps, the second layer — with the next \(l_2\) lamps and so on. The last n-th layer should be decorated with the last \(l_n\) 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:
- Any two lamps that follow consecutively in the same layer should have different colors.
- The sets of used colors in every two neighbouring layers must be different. We consider unordered sets (not multisets), where every color occurs no more than once. So the number of lamps of particular color does not matter.
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\).
Input
The first line contains three integers \(n\), \(m\) and \(p\) \((1 ≤ n, m ≤ 10^6, 2 ≤ p ≤ 10^9)\) which are the number of the tree's layers, the number of the lamps' colors and module correspondingly. The next line contains \(n\) integers \(l_i\) (1 ≤ \(l_i\) ≤ 5000, ).
Output
Print the only integer — the number of garlands modulo p.
Examples
input
3 2 1000
3 1 2
output
8
input
2 3 1000
2 2
output
24
input
1 1 1000
5
output
0
Note
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.
Figure for the first sample:
题意
给一个n层能挂彩球的圣诞树(二维数组),每一层\(l[i]\)的大小固定,给定m种颜色,要求每一层的颜色集合不同,同一层相邻彩球颜色不同,问有多少种放法,结果对p取模
思路
一眼DP,但还是要一个个解决子问题
子问题一,先考虑第 \(i\) 层上能放多少种颜色,设\(f[i][j]\)表示长度为\(i\)的层放\(j\)种颜色的球的方案数:
这里的递推就是第二类斯特林数(懒得画图,语言来描述吧)
设某一层长度为\(n\),颜色数为\(k\)
如果前\(n-1\)个球只用了\(k-1\)种颜色,那么最后一个球肯定要用剩下的那\(1\)种颜色,那么这部分的方案数就包含上一步只含\(k-1\)种颜色的递推,\(f[l - 1][k - 1] * 1 = f[l - 1][k - 1]\),
如果前\(n-1\)个球已经用了\(k\)种颜色,那么最后一个球肯定要用与第\(l - 1\)个球不同的颜色,因为第\(l - 1\)个球可能有\(k\)种(都能涉及)颜色,第\(l\)个球只可能用与它不同的颜色,所以第\(l\)个球可能有\((k - 1)\)种颜色,那么这部分的方案数就包含上一步含\(k\)种颜色的递推\(f[l - 1][k] * (k - 1)\),
故\(f[i][j] = f[i−1][j−1] + f[i−1][j]∗(j−1)\)
长度为\(l[i]\),那么最多用的颜色可以是\(l[i]\),预处理长度为\(l[i]\)的一层最多能用多少种方案数,可以累加,即设\(s[l[i]] = f[l[i]][1] * C_m^1 * 1 ! + f[l[i]][2] * C_m^2 * 2 !+ ... + f[l[i]][l[i]] * C_m^i * i !\),这里累加预处理的复杂度是\(O(i ^ 2)\)
子问题二,因为本层和上一层的颜色集合不能是一致的,可以开一个新的动态规划,用 \(dp[i][j]\)表示第\(i\)层用 \(j\) 种颜色的合法方案数(前提,第\(1\)到\(i−1\)层合法)
那么,它的转移方程式\(dp[i][j]\)=\(f[l[i]][j] * (s[i - 1] - dp[i - 1][j] * j !)\)
(翻译:这层本身方案数 * (上一层方案数 - 之前存在刚好和本层颜色方案相同的情况))
得 \(s[i] = \sum_{j=1}^{l[i]} dp[i][j] * C_m ^ j * j !\),继续处理,\(C_m^i * i ! == m ^ \underline{i}\) \(==\)\(m^\underline{i - 1} *(m - i + 1)\)(可以预处理)
预处理后,最后一种的方案数\(s[n]\)即为答案,复杂度\(O(l ^ 2 + L)\)
AC代码
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define int long long
#define ull unsigned long long
#define PII pair<int,int>
using namespace std;
typedef long long LL;
const int N = 5e3 + 1;
const int mod = 1e9 + 7;
const double pi = acos(-1.0);
int T, n, m, p;
int l[N];
int f[N][N];//子问题一
int fact[N], C[N];//阶乘,组合数
vector<int> gra[N];//学别人的,全图开一个vector优化空间
int s[N];
//取模前可能会爆int,如果没有define int ll的习惯取模前还是要加上ll
//思路讲的贼清楚,可以对应上,就不逐字符注释了
void solve() {
for (int i = 1; i <= n; i++) {
cin >> l[i];
gra[i].resize(l[i] + 1);
}//初始化
f[0][0] = 1;
for (int i = 1; i < N; i++) {
for (int j = 1; j <= i; j++) {
f[i][j] = f[i - 1][j - 1] + 1LL * f[i - 1][j] * (j - 1) % p;
if (f[i][j] >= p) {
f[i][j] -= p;
}
}
}//子问题一预处理
fact[0] = 1; C[0] = 1;
for (int i = 1; i < N; i++) {
fact[i] = 1LL * fact[i - 1] * i % p;
}//阶乘预处理
for (int i = 1; i <= m && i < N; i++) {
C[i] = 1LL * C[i - 1] * (m - i + 1) % p;
}//组合数预处理
s[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= l[i]; j++) {
gra[i][j] = 1LL * s[i - 1] * f[l[i]][j] % p * C[j] % p;
if (i > 1 && j <= l[i - 1]) {
gra[i][j] -= 1LL * fact[j] * gra[i - 1][j] % p * f[l[i]][j] % p;
if (gra[i][j] < 0) {
gra[i][j] += p;
}
}
s[i] += gra[i][j];
if (s[i] >= p) {
s[i] -= p;
}
}
}
cout << s[n] << endl;
return;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
while (cin >> n >> m >> p) {
solve();
}
return 0;
}
/*
i raised a cute kitty in my code,
my friend who pass by can touch softly on her head:)
/l、
Meow~(゚、 。7
|、 ~ヽ
じしf_,)ノ
*/
标签:种颜色,12,Garland,int,容斥,colors,Edward,lamps,Year 来源: https://www.cnblogs.com/peace0218/p/15449546.html