题目
Description
公元11380年,一颗巨大的陨石坠落在南极。于是,灾难降临了,地球上出现了一系列反常的现象。当人们焦急万分的时候,一支中国科学家组成的南极考察队赶到了出事地点。经过一番侦察,科学家们发现陨石上刻有若干行密文,每一行都包含5个整数:
1 1 1 1 6
0 0 6 3 57
8 0 11 3 2845
著名的科学家SS发现,这些密文实际上是一种复杂运算的结果。为了便于大家理解这种运算,他定义了一种SS表达式:
1. SS表达式是仅由’{’,’}’,’[’,’]’,’(’,’)‘组成的字符串。
2. 一个空串是SS表达式。
3. 如果A是SS表达式,且A中不含字符’{’,’}’,’[’,’]’,则(A)是SS表达式。
4. 如果A是SS表达式,且A中不含字符’{’,’}’,则[A]是SS表达式。
5. 如果A是SS表达式,则{A}是SS表达式。
6. 如果A和B都是SS表达式,则AB也是SS表达式。
例如
()(())[]
{()[()]}
{{[[(())]]}}
都是SS表达式。
而
()([])()
[()
不是SS表达式。
一个SS表达式E的深度D(E)定义如下:
例如(){()}[]的深度为2。
密文中的复杂运算是这样进行的:
设密文中每行前4个数依次为L1,L2,L3,D,求出所有深度为D,含有L1对{},L2对[],L3对()的SS串的个数,并用这个数对当前的年份11380求余数,这个余数就是密文中每行的第5个数,我们称之为?神秘数?。
密文中某些行的第五个数已经模糊不清,而这些数字正是揭开陨石秘密的钥匙。现在科学家们聘请你来计算这个神秘数。
Input
共一行,4个整数
L
1
,
L
2
,
L
3
,
D
L1,L2,L3,D
L1,L2,L3,D。相邻两个数之间用一个空格分隔。
(
0
<
=
L
1
<
=
10
,
0
<
=
L
2
<
=
10
,
0
<
=
L
3
<
=
10
,
0
<
=
D
<
=
30
)
(0 <= L1 <= 10,0 <= L2 <= 10,0 <= L3 <= 10,0 <= D <= 30)
(0<=L1<=10,0<=L2<=10,0<=L3<=10,0<=D<=30)
Output
共一行,包含一个整数,即神秘数。
Sample Input
1 1 1 2
Sample Output
8
思路
我一开始设的状态:
d
p
[
a
]
[
b
]
[
c
]
[
d
]
dp[a][b][c][d]
dp[a][b][c][d] 为有
a
a
a 个 {},
b
b
b 个[],
c
c
c 个()时深度为
d
d
d 的个数。
然而无法转移…… 因为没法控制子状态中d的最大值。
于是想另一种方法:
d
p
[
a
]
[
b
]
[
c
]
[
d
]
dp[a][b][c][d]
dp[a][b][c][d] 为有
a
a
a 个{},
b
b
b 个[],
c
c
c 个()时深度不超过
d
d
d 的个数
用排列组合将子状态弄一起就行了。
转移:算出当前串两个部分答案的乘积即可。
另外要注意一下枚举的循环顺序。
其他就没什么问题了吧。
完事了。 上代码。
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <map>
#include <stack>
#include <cmath>
using namespace std;
const int p = 11380;
int a, b, c, d, dp[15][15][15][35];
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1)+(x << 3)+(ch ^ 48);
ch = getchar();
}
return x*f;
}
int search(int aa, int bb, int cc, int dd) {
int ans = 0;
if (!dd && (aa | bb | cc)) return 0;
if (!(aa|bb|cc)) return dp[aa][bb][cc][dd] = 1;
if (dp[aa][bb][cc][dd]) return dp[aa][bb][cc][dd];
for (int i = 0; i <= cc; i++) {
if (i) ans = (ans+search(0, 0, i-1, dd-1) % p * search(aa, bb, cc-i, dd) % p) % p;
for (int j = 0; j <= bb; j++) {
if (j) ans = (ans+search(0, j-1, i, dd-1) % p * search(aa, bb-j, cc-i, dd) % p) % p;
for (int k = 1; k <= aa; k++)
ans = (ans+search(k-1, j, i, dd-1) % p*search(aa-k, bb-j, cc-i, dd) % p) % p;
}
}
return dp[aa][bb][cc][dd] = ans;
}
int main() {
a = read(); b = read(); c = read(); d = read();
search(a, b, c, d);
if(d) search(a, b, c, d-1);
int ans = dp[a][b][c][d]-(d?dp[a][b][c][d-1]:0);
printf("%d", (ans+p)%p);
return 0;
}