*题解:P5694 [NOI2001] 陨石的秘密
解析
有一个好想的状态是设 \(f_{l_1,l_2,l_3,d}\) 表示含有 \(l_1\) 对 {},\(l_2\) 对 [],\(l_3\) 对 (),深度为 \(d\) 的 SS 串个数。
对于转移,考虑从某个状态加上一对括号转移过来。问题在于可加括号的地方实在太多,并且还有括号种类的影响。所以我们需要对这两者进行限定:将一个 SS 表达式 \(S\) 分隔成 \(AB = S\),其中 \(A,B\) 也为 SS 表达式,然后加一对括号把 \(A\) 包裹起来变为 \((A)B\),\([A]B\) 或 \(\{A\}B\),把 \(S\) 的信息转移到这些串。可以发现,每个非空 SS 串能且仅能分离出一个唯一的 \(B\) 串,这也就保证了我们的统计是不重不漏的。
在列状态转移方程之前,可以预见的是,我们在转移时需要枚举 \(A\) 和 \(B\) 的深度。此时有一个经典技巧是将状态改写,求深度不超过 \(d\) 的 SS 串个数,求答案时再做差分。
按照改良后的状态,可以列出状态转移方程:
加小括号:
\[\large f_{l_1,l_2,l_3,d} \leftarrow f_{l_1,l_2,l_3,d} + \sum_{z = 0} ^ {l_3 - 1} f_{0,0,z,d - 1} \cdot f_{l_1,l_2,l_3 - z - 1,d}
\]
加中括号:
\[\large f_{l_1,l_2,l_3,d} \leftarrow f_{l_1,l_2,l_3,d} + \sum_{y = 0} ^ {l_2 - 1}\sum_{z = 0} ^ {l_3 - 1} f_{0,y,z,d - 1} \cdot f_{l_1,l_2 - y - 1,l_3 - z,d}
\]
加大括号:
\[\large f_{l_1,l_2,l_3,d} \leftarrow f_{l_1,l_2,l_3,d} + \sum_{x = 0}^{l_1 - 1}\sum_{y = 0} ^ {l_2 - 1}\sum_{z = 0} ^ {l_3 - 1} f_{x,y,z,d - 1} \cdot f_{l_1 - x - 1,l_2 - y,l_3 - z,d}
\]
代码
/*
*/
#include <bits/stdc++.h>
#define mid ((1ll * l + r) >> 1)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 30 + 5,M = 10 + 5,L = 19,L2 = 17,mod = 11380;
int f[M][M][M][N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int L1,L2,L3,d;
cin>>L1>>L2>>L3>>d;
if(d == 0){
if(!L1 && !L2 && !L3){
cout<<1;
}else{
cout<<0;
}
return 0;
}
int n = (L1 + L2 + L3) * 2;
f[0][0][0][0] = 1;
for(int dep = 1;dep <= d;dep++){
f[0][0][0][dep] = 1;
for(int l3 = 0;l3 <= L3;l3++){
for(int l2 = 0;l2 <= L2;l2++){
for(int l1 = 0;l1 <= L1;l1++){
for(int z = 0;z <= l3;z++){
if(z != l3){
f[l1][l2][l3][dep] = (f[l1][l2][l3][dep] + f[0][0][z][dep - 1] * f[l1][l2][l3 - z - 1][dep] % mod) % mod;
}
for(int y = 0;y <= l2;y++){
if(y != l2){
f[l1][l2][l3][dep] = (f[l1][l2][l3][dep] + f[0][y][z][dep - 1] * f[l1][l2 - y - 1][l3 - z][dep] % mod) % mod;
}
for(int x = 0;x < l1;x++){
f[l1][l2][l3][dep] = (f[l1][l2][l3][dep] + f[x][y][z][dep - 1] * f[l1 - x - 1][l2 - y][l3 - z][dep] % mod) % mod;
}
}
}
}
}
}
}
cout<<(f[L1][L2][L3][d] + mod - f[L1][L2][L3][d - 1]) % mod;
return 0;
}

浙公网安备 33010602011771号