CF1924D Balanced Subsequences

题意简述

n 个左括号和 m 个右括号,求最长合法括号子序列长度为 2k 的括号序列的数量,对 109+7 取模。多组数据。

T3×103,n,m,k2×103

分析

可能需要的前置知识:

如何求一个字符串的最长合法括号子序列?

维护一个括号栈,若遇到左括号则直接压入栈,若遇到右括号则取出栈顶左括号匹配(此时最长合法括号子序列长度 +2),若没有,则该右括号失配。

下面进入正题。

首先,长度为 2k 的合法括号序列包含 k 个左括号和 k 个右括号。

首先判掉 k>n,k>m 的情况,那么将会剩下 nk 个废物左括号和 mk 个废物右括号。

首先肯定是废物右括号在前,废物左括号在后,否则这一对废物括号会扩充合法括号子序列的长度。

将括号序列抽象成折线,初始位置在 (0,0),加入一个括号就让横坐标 +1,此时若该括号为左括号则让纵坐标 +1,否则让纵坐标 -1。也就是说,折线要么往右上方走,要么往右下方走。

而我们会有 mk 个废物右括号会失配,所以最终在某一横坐标之下,纵坐标会到达 km,因为当废物右括号失配时,根据前置知识,此时的括号栈中没有多余的左括号了,也就是说前面的括号肯定全部匹配完毕了。

而最终我们要达到坐标 (n+m,nm)

题意转化为求一条 (0,0) 开始,(n+m,nm) 结束,路径上要到达并不能越过 y=km 的折线数量。

发现,到达并不能越过 这个限制实在是太紧了。考虑类似将 =k 转化为 kk1,设 ansk 为允许折线越过 y=km 的方案数,则原题答案转化为 anskansk1

考虑怎么求 ansk。考虑折线第一次到达 y=km 的那个点,将那个点之后的折线按照 y=km 轴对称一下,原题又转化为从 (0,0) 走到 (n+m,2knm) 的方案数,这是一个组合数,为 ansk=(n+mk)。(简单推式子可得)

所以最终答案为 (n+mk)(n+mk1)

代码仅展示关键部分。

点击查看代码
int n,m,k;
int C[maxn][maxn];
void init(int lim){
	C[0][0]=1;
	rep(i,1,lim){
		C[i][0]=1;
		rep(j,1,i)C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
	}
}
void solve_the_problem(){
	n=rd(),m=rd(),k=rd();
	if(k>m||k>n)return (void)puts("0");
	write((C[n+m][k]-C[n+m][k-1]+mod)%mod,10);
}
/*

*/

作者:dcytrl

出处:https://www.cnblogs.com/dcytrl/p/17993567

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   dcytrl  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示