P5694 [NOI2001] 陨石的秘密
一道有趣的高维计数 DP。
题目大意
定义合法的括号串为:
- 仅由
()
,[]
,{}
组成; - 空串是合法括号串;
- 是合法括号串且不含
[]
,{}
,则 是合法括号串; - 是合法括号串且不含
{}
,则 是合法括号串; - 是合法括号串,则 是合法括号串;
- 均为合法括号串,则 也是合法括号串。
定义一个括号串的深度为最大的括号嵌套数,求使用了 对 {}
, []
, ()
且深度为 的合法括号串数量,答案对 取模。
大体思路
由于 均不大,直接使用高维 DP,状态定义照抄题面。故定义 表示使用了 对大、中、小括号且深度为 的数量。
状态转移自然是将当前串分割成两个串 ,使得 的深度为 ,用某一种括号去套一个合法的串 。由于嵌套一层后深度 ,要求这个合法串 的深度不大于 。
这时,我们发现需要枚举所有 的深度,太过麻烦,因此对 做前缀和处理,即将状态定义改为 表示使用了 对大、中、小括号且深度 的数量。
对当前串 TS
,可以通过一个括号嵌套变成 (T)S
,[T]S
,{T}S
。我们可以通过枚举 中包含多少 {}, [], ()
,得到状态转移方程:
特殊地,对于 时,。
输出时,通过前缀和做差即可,需要特判 以及 的情况。时间复杂度 。
完整代码
#include <bits/stdc++.h> using namespace std; #define rep(ii,aa,bb) for(re int ii = aa; ii <= bb; ii++) #define Rep(ii,aa,bb) for(re int ii = aa; ii >= bb; ii--) typedef long long ll; typedef unsigned long long ull; typedef double db; typedef pair<int, int> PII; const ll mod = 11380; namespace IO_ReadWrite { #define re register #define gg (p1 == p2 && (p2 = (p1 = _buf) + fread(_buf, 1, 1<<21, stdin), p1 == p2) ? EOF :*p1++) char _buf[1<<21], *p1 = _buf, *p2 = _buf; template <typename T> inline void read(T &x){ x = 0; re T f=1; re char c = gg; while(c > 57 || c < 48){if(c == '-') f = -1;c = gg;} while(c >= 48 &&c <= 57){x = (x<<1) + (x<<3) + (c^48);c = gg;} x *= f;return; } inline void ReadChar(char &c){ c = gg; while(!isalpha(c)) c = gg; } template <typename T> inline void write(T x){ if(x < 0) putchar('-'), x = -x; if(x > 9) write(x/10); putchar('0' + x % 10); } template <typename T> inline void writeln(T x){write(x); putchar('\n');} } using namespace IO_ReadWrite; ll L1, L2, L3, D, f[35][12][12][12]; int main () { read(L1); read(L2); read(L3); read(D); f[0][0][0][0] = 1; rep(d, 1, D) { f[d][0][0][0] = 1; rep(i, 0, L1) rep(j, 0, L2) rep(k, 0, L3) { if(!i && !j && !k) continue; rep(a, 0, i - 1) rep(b, 0, j) rep(c, 0, k) (f[d][i][j][k] += f[d - 1][a][b][c] * f[d][i-1 - a][j - b][k - c]) %= mod; rep(b, 0, j - 1) rep(c, 0, k) (f[d][i][j][k] += f[d - 1][0][b][c] * f[d][i][j-1 - b][k - c]) %= mod; rep(c, 0, k - 1) (f[d][i][j][k] += f[d - 1][0][0][c] * f[d][i][j][k-1 - c]) %= mod; } } if(!D) writeln(((!L1 && !L2 && !L3) ? 1 : 0)); else if(!L1 && !L2 && !L3) writeln(0); else writeln((f[D][L1][L2][L3] - f[D - 1][L1][L2][L3] + mod) % mod); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具