把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

CF1264D Beautiful Bracket Sequence

题面传送门
我们考虑怎么确定一个序列的深度。
可以肯定的是我们选出来的子序列一定是长度为2x的,前x个为(,后x)
如果一个序列是确定的,我们显然可以维护两个值d1,d2表示当前位置左边的(个数与右边的)个数。
因为每次要么是d1加一,要么是d2减一,所以这个位置是确定的。
这就启发我们枚举这个位置。
设左边的(个数为l1?l2,右边为r1r2
假设右边所有?都变成)则我们可以设d=r1+r2l1表示左边要变成(的个数。
然后我们枚举左边变成的个数就可以得到式子i=0d(i+l1)Cil2Cr2di
然后随便O(n)预处理一下这个东西就可以O(n2)计算了。
这个式子肯定有办法化简,让我们把它拆开来。
l1i=0dCil2Cr2dii=0diCil2Cr2di
前面那个显然是l1Cil2+r2,后面那个是这样的:
i=0dl2Ci1l21Cr2di=l2Cd1l2+r21
然后就可以算了,时间复杂度O(n)
code:

#include <vector>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#include<bitset>
#include<set>
#include<map>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define l(x) x<<1
#define r(x) x<<1|1
#define re register
#define ll long long
#define db double
#define N 1000000
#define eps (1e-5)
#define mod 998244353
#define U unsigned
using namespace std;
int n,l1,l2,r1,r2,d;char s[N+5];ll inv[N+5],frc[N+5],now,ans;
I ll mpow(ll x,int y=mod-2){ll ans=1;while(y) y&1&&(ans=ans*x%mod),y>>=1,x=x*x%mod;return ans;}
int main(){
	freopen("1.in","r",stdin);
	re int i;scanf("%s",s+1);n=strlen(s+1);frc[0]=1;
	for(i=1;i<=n;i++) r1+=(s[i]==')'),r2+=(s[i]=='?');
	for(i=1;i<=n;i++) frc[i]=frc[i-1]*i%mod;now=mpow(frc[n]);for(i=n;~i;i--) inv[i]=now,now=now*i%mod;
	for(i=1;i<n;i++){
		l1+=(s[i]=='(');l2+=(s[i]=='?');r1-=(s[i]==')');r2-=(s[i]=='?');if(l1+l2<r1||r1+r2<l1) continue;d=r1+r2-l1;
		ans+=inv[l2+r2-d]*(l1*frc[l2+r2]%mod*inv[d]%mod+l2*frc[l2+r2-1]%mod*inv[d-1]%mod)%mod;
	}
	printf("%lld\n",ans%mod);
}
posted @   275307894a  阅读(32)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
浏览器标题切换
浏览器标题切换end
点击右上角即可分享
微信分享提示