「CF1831E」Hyperregular Bracket Strings 题解
本文网址:https://www.cnblogs.com/zsc985246/p/17565768.html ,转载请注明出处。
前言
没见过的套路,写篇题解记录一下。
传送门
「CF1831E」Hyperregular Bracket Strings
题目大意
给定 和 个区间 ,你需要找出满足以下条件的合法括号序列个数:
-
序列的长度为 。
-
,区间 的括号序列合法。
答案对 取模。
。
思路
看到括号序列,直接把 (
看成 ,)
看成 。
我们知道,对于一个长度为 的合法括号序列,令它的前缀和为 ,那么 。
那么我们就将题目转化为如下:
求由 和 组成且满足 条限制的长度为 的合法序列 个数,其中第 条限制为区间 合法。
一个区间 合法当且仅当 。
首先如果 和 不相交,可以分开计算答案,所以我们只需要处理相交的情况。
如果 ,即两个区间为包含关系,发现区间 和 的括号序列拼接起来一定合法。
如果 ,即两个区间不互相包含,根据上方的结论,,可以推出 ,也就可以推出区间 也必须合法。
这个时候我们就可以使用套路。我们给每个区间随机分配一个权值,一个位置的权值就是包含这个位置的区间的权值异或和。
这可以使用前缀异或和维护。这样做的好处是所有权值相同的位置拿出来一定构成合法序列,并且每个位置恰好属于一个合法序列。
括号序列有一个结论:长度为 的合法括号序列的方案数是卡特兰数第 项。对每个权值都算一次卡特兰数,相乘即为答案。
代码实现
不建议使用 rand 和 mt19937,因为值域不够大,容易冲突。除了使用代码中的 mt19937_64 之外,还可以使用 hash。
#include<bits/stdc++.h>
#define ll long long
#define For(i,a,b) for(ll i=(a);i<=(b);++i)
#define Rep(i,a,b) for(ll i=(a);i>=(b);--i)
const ll N=1e6+10;
using namespace std;
const ll p=998244353;
//组合数模板
ll ksm(ll a,ll b){ll bns=1;while(b){if(b&1)bns=bns*a%p;a=a*a%p;b>>=1;}return bns;}
ll jc[N],inv[N];
void init(ll n){jc[0]=1;For(i,1,n)jc[i]=jc[i-1]*i%p;inv[n]=ksm(jc[n],p-2);Rep(i,n-1,0)inv[i]=inv[i+1]*(i+1)%p;}
ll C(ll n,ll m){if(m<0)return 1;if(n<m)return 0;return jc[n]*inv[m]%p*inv[n-m]%p;}
//随机数初始化
mt19937_64 rnd(random_device{}());
uniform_int_distribution<ll>dist(0,LLONG_MAX);
ll n,m,k;
ll a[N];
ll Catalan(ll x){//卡特兰数第x项
return (C(2*x,x)-C(2*x,x-1)+p)%p;
}
void mian(){
scanf("%lld%lld",&n,&k);
For(i,0,n)a[i]=0;
For(i,1,k){
ll l,r;
scanf("%lld%lld",&l,&r);
//分配随机权值
ll t=dist(rnd);
a[l]^=t,a[r+1]^=t;
}
map<ll,ll>vis;
For(i,1,n)vis[a[i]^=a[i-1]]++;//统计各个权值的数量
ll ans=1;
for(auto i:vis){
if(i.second&1)ans=0;//不合法
else ans=ans*Catalan(i.second/2)%p;//计算答案
}
printf("%lld\n",ans);
}
int main(){
init(1e6);//组合数预处理
int T=1;
scanf("%d",&T);
while(T--)mian();
return 0;
}
尾声
如果你发现了问题,你可以直接回复这篇题解
如果你有更好的想法,也可以直接回复!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现