题解 CF1264D1 Beautiful Bracket Sequence (easy version)
1.题解 CF1059E Split the Tree2.题解 CF932D Tree3.题解CF1775C4.题解 CF1729D5.题解CF1729C
6.题解 CF1264D1 Beautiful Bracket Sequence (easy version)
传送门。
题意
一个含未知字符的括号序列,一个括号序列的权值是这个括号序列的最大深度。问所有可能的括号序列的权值和为多少。
分析
我们寻找一下深度的快速计算方式。
可以发现两个巧妙的性质。
- 以某一个位置分割,左边的左括号数量和右边的右括号数量的较小值就是这个位置的最大延伸深度。
- 由于我们的全局最大深度就是所有位置的最大延伸深度的最大值,此时,我们可以发现,此时,我们左边的左括号数应当等于右边右括号的数量。
证明:
- 将左边的右括号全删,右边的左括号全删,显然最优。
- 首先,左侧左括号的数量是一个单调递增的函数,右侧右括号的数量是一个单调递减的函数,我们的最大延伸深度就是两个函数的较下的那条线,并且总有一边会变化,且只变化 1,因此,相等处即为最大值。
然后处理问号,我们从性质 2 出手,枚举最大值的分割点,然后再枚举深度,于是就知道了左边的问号有多少个变成左括号,简单的组合就好了。
时间复杂度:
#include <bits/stdc++.h> #define int long long using namespace std; const int N = 1e6+5; const int MOD = 998244353; inline int poww(int x,int y) { int res=1; while(y) { if(y&1) res=res*x%MOD; x=x*x%MOD; y>>=1; } return res; } int n, m,ans; char s[N]; int L[N],R[N],qz[N],hz[N],fac[N],inv[N],inf[N]; inline void ADD(int &u,int v) {u=(u+=v)>=MOD?u-MOD:u;} inline int C(int n,int m) { if(n<m) return 0; return fac[n]*inv[m]%MOD*inv[n-m]%MOD; } signed main() { scanf("%s",s+1),n=strlen(s+1); fac[0]=inf[1]=inv[1]=inv[0]=1; for(int i=1; i<N; ++i) fac[i]=fac[i-1]*i%MOD; for(int i=2; i<N; ++i) inf[i]=(MOD-(int)(MOD/i))*inf[MOD%i]%MOD; for(int i=2; i<N; ++i) inv[i]=inv[i-1]*inf[i]%MOD; for(int i=1; i<=n; ++i) L[i]=L[i-1]+(s[i]=='('),qz[i]=qz[i-1]+(s[i]=='?'); for(int i=n; i>=1; --i) R[i]=R[i+1]+(s[i]==')'),hz[i]=hz[i+1]+(s[i]=='?'); for(int i=1; i<n; ++i) { int cntl=L[i],cntr=R[i+1],yl=qz[i],yr=hz[i+1]; for(int j=max(cntl,cntr); j<=min(i,n-i); ++j) ADD(ans,j*C(yl,j-cntl)%MOD*C(yr,j-cntr)%MOD); } cout<<ans; return 0; }
合集:
CodeForces
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现