首页 > 其他分享 >CF629C题解

CF629C题解

时间:2023-03-31 15:46:18浏览次数:52  
标签:数起 题解 tr long 括号 tl CF629C ml

CF629C

这里更容易进入且有翻译

题意

给定长度为 \(m\) 的仅含 () 的字符串,为其左右补上两个字符串使其达到指定长度 \(n\) 且合法, 需补足字符串合计长度 \(n - m\) 满足 \(n - m \le 2000\)。

解析

字符串合法条件为:

左右括号总数相等;

从左数起在任意位置上左括号数量不小于右括号数量。

首先思考下左侧的合法状况,设 \(f^1_{i,j}\) 为前 \(i\) 个字符使用了 \(j\) 个 ( 时的方案数,有 \(f^1_{0,0} = 1\),得到状态转移方程为:

\[f^1_{i,j} = f^1_{i - 1, j - 1} + f^1_{i - 1, j} \]

然后思考下另一侧,题意表明左右括号总数相等,且从左数起一定有左括号数 \(l\) 不小于右括号数 \(r\),即

\[l \ge r \]

可化成

\[\frac{n}{2} - l \le \frac{n}{2} - r \]

即从右数起在任意位置上右括号数量不小于左括号数量。由此,可设 \(f^2_{p, q}\) 为从右数起前 \(p\) 个字符使用了 \(q\) 个 ) 时的方案数,状态转移方程同上。

最后,枚举左右状态并利用乘法原理即可算出答案,设需补足的右括号共为 \(tr\) 个,对于任意状态下都有 \(p = n - m - i\) 和 \(q = tr - (i - j)\)。

代码

#include<bits/stdc++.h>
#define LL long long 

using namespace std;

vector<vector<LL> > dp1(2005, vector<LL>(2005, 0)), dp2(2005, vector<LL>(2005, 0));
LL mod = 1000000007;
//要开long long,不然#4可能会炸精度

signed main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

	LL n, m, tl = 0, tr, nl = 0, nr = 0, ml = 0, mr = 0, ans = 0;
	string s;
	cin >> n >> m;
	getline(cin, s);
	getline(cin, s);

	for (int i = 0; i < m; i++)
	{
		tl += s[i] == '(';
		nl += 2 * (s[i] == ')') - 1; //计算当前右左括号数量差
		ml = max(ml, nl); //存储最大差值
						  //左方插入字符串左右括号数量差至少达到ml
	}
	//反向遍历一次计算左右括号数量差值,作用同上
	for (int i = m - 1; i > -1; i--)
	{
		nr += 2 * (s[i] == '(') - 1;
		mr = max(mr, nr);
	}

	if (tl > n / 2 || m - tl > n / 2 || n & 1)
	{
		//将完全不合法的情况直接排除
		cout << "0";
		return 0;
	}
	tl = n / 2 - tl;
	tr = n - m - tl;
	//tl和tl分别表示外部插入字符串总共需要的左右括号数量

	//计算左侧合法情况
	dp1[0][0] = 1;
	for (LL i = 1; i <= min(n - m, tl * 2); i++)
		for (LL j = 0; j <= min(i, tl); j++)
			if (i - j <= j && i - j <= tr)
				dp1[i][j] = (dp1[i - 1][j - 1] + dp1[i - 1][j]) % mod;

	//计算右侧合法情况
	dp2[0][0] = 1;
	for (LL i = 1; i <= min(n - m, tr * 2); i++)
		for (LL j = 0; j <= min(i, tr); j++)
			if (i - j <= j && i - j <= tl)
				dp2[i][j] = (dp2[i - 1][j - 1] + dp2[i - 1][j]) % mod;

	//乘法原理计算答案
	for (int i = 0; i <= n - m; i++)
		for (int j = 0; j <= i; j++)
			if (j - (i - j) >= ml && tr - (i - j) - (tl - j) >= mr) //判断左右侧的左右括号数是否达到要求
				ans = (ans + dp1[i][j] * dp2[n - m - i][tr - i + j]) % mod;

	cout << ans;
}

最后祝各位顺利AC。 >w<

标签:数起,题解,tr,long,括号,tl,CF629C,ml
From: https://www.cnblogs.com/ItsAiHAn/p/17276473.html

相关文章

  • [ARC128D] Neq Neq 题解
    不难考虑设\(f_i\)表示现在处理了前\(i\)个数,第\(i\)个数必选得到的方案数。由于\(a_n\)不可能被删掉(需要一个\(a_{n+1}\)),所以答案即为\(f_n\)。对\(f_i\),我们考虑前一个被保留的数\(j\),问题转化成被\(i,j\)夹住的一段连续的数可不可以全部删掉,分类讨论:\(j=i-1\)......
  • 洛谷9150题解
    考虑把\(i\tok_i\)连边,这样形成若干个环。考虑断环为链并且把链复制一份接到后面。考虑求出从一个点集开始拓展能够到达的点集\(S1_i\)。显然\(S1_i\)在环上是连续的,设\(r_i\)表示第\(i\)个节点拓展能得到的右端点。考虑每个节点\(i\)所在强连通分量的点集合\(S2\)。可以证明\(......
  • 省选欢乐赛 题解
    昨天沈老师神仙场整不会了。然后今天经典老题。不是很懂为什么三道题题目名称都是Delov。卷王发现如果答案为第\(t\)秒,那么这个序列一定是一个\(1\)、两个连续的\(1\)、三个连续的\(1\)……一直到\(t\)个连续的\(1\)(中间可能有没有的项,即不操作)异或起来。那随便跑个状......
  • php 浮点数转int精度丢失问题解决办法
    方案一:先将浮点金额strval后再转int。(推荐)$param['order_price']=intval(strval($param['order_price']*100)); 方案二: echoround(19.99*100); 这种方案出来是......
  • P4156 [WC2016]论战捆竹竿 题解
    题目链接题意描述给定一个字符串\(S\),你初始拥有一个空串\(T\),每次可以选择这个字符串的一个Border,去掉它后接在\(T\)的后面,操作后\(S\)不变,给出一个上限\(w\),求......
  • CF1295E Permutation Separation 题解 线段树优化dp
    题目链接:https://codeforces.com/problemset/problem/1295/E题目大意:将排列\(p_1,p_2,\ldots,p_n\)先分成\(p_1,\ldots,p_k\)与\(p_{k+1},\ldots,p_n\)两个......
  • 【题解】[HEOI2013]SAO
    题目分析:考虑这是一个树形图,所以就先直接当作树来做。这个题其实就是让我们求解有多少种拓扑序而且题目中边方向的限制其实就是在限制拓扑序的前后,而一般这种题在设计\(......
  • 【题解】Codeforces Round 861(CF1808)A - E1
    我忘记了今天有阳间CF,所以就开打的很晚,所以只是说一下做法,代码实现....还是算了吧。但是我也看了,我的思路其他的人都有写,所以这个做法正确性没问题。A.LuckyNumbers题......
  • CF1009F 题解
    一、题目描述:给定一棵以 1 为根,n 个节点的树。设 d(u,x) 为 u的子树中到 u 距离为 x 的节点数。对于每个点,求一个最小的 k,使得 d(u,k) 最大。 二、......
  • CentOS7中远程连接数据库连不上的问题解决方法
      当远程连接数据库连接不起来时:可能原因:1.检查网络防火墙或其他安全设置是否阻止了连接  2.mysql服务是否启动,查看systemctlstatusmysql3.是否提前授权:......