首页 > 其他分享 >[COCI2007-2008#1] ZAPIS 题解

[COCI2007-2008#1] ZAPIS 题解

时间:2024-02-08 20:01:59浏览次数:28  
标签:texttt int 题解 COCI2007 括号 MAXN 序列 2008 dp

题目传送门

前置知识

区间型动态规划

思考过程

这题也算是一道很经典的问题了(?)。

看见 \(n \leq 200\),不难想到复杂度为 \(O(n^3)\) 的区间型动态规划。

题面中有这么一段话。

  • 空串是规则括号序列。
  • 如果 \(\texttt A\) 是规则括号序列,那么 \(\texttt{(A) [A] {A}}\) 都是规则括号序列。
  • 如果 \(\texttt A,\texttt B\) 都是规则括号序列,那个序列 \(\texttt {AB}\) 也是规则括号序列。

这相当于直接告诉了我们动态规划的转移方程。

设 \(dp(l,r)\) 表示由 \([l,r]\) 之间的字符组成的字符串有多少种不同的括号序列。

定义函数 \(g(i,j)\) 表示第 \(i\) 个字符与第 \(j\) 个字符可以组成多少对不同的括号。

  • 对于空串而言,令 \(dp(l,l-1)=1\)。
  • 对于 \(\texttt{(A)}\) 这一类的括号序列,可以写出转移方程 \(dp(l,r)\leftarrow dp(l,r)+g(l,r)\times dp(l+1,r-1)\)。
  • 对于 \(\texttt{AB}\) 类型的接下来我们重点讨论。

思路 \(1\)

我们能不能直接枚举一个位置 \(p\),写出转移方程 \(dp(l,r) \leftarrow dp(l,r) + \sum_{p=l+1}^{r-1} dp(l,p) \times dp(p+1,r)\)。

经过思考不难发现这样是不行的,通过样例 \(1\) 就可以发现。

如果按照上述思想,\(dp(1,6)=dp(1,4) \times dp(5,6) +dp(1,2) \times dp(3,6)=2\),但是答案是 \(1\)。

这个转移错就错在重复计算了答案。

思路 \(2\)

沿用思路 \(1\),既然知道问题出在哪,那么我们思考一下应该如何解决。

算重就是因为存在两个位置 \(p_1,p_2\),满足 \([p_1,p_2]\) 构成合法的括号序列。

那么应该怎么解决呢?解决问题的关键就在于在转移的过程中不存在 \(p_1,p_2\) 两个转移点使得 \([p_1,p_2]\) 被重复计算贡献。

考虑强制要求由 \([l,p]\) 构成的合法括号序列 \(l,p\) 匹配。这样便可以符合要求。

\(dp(l,r)\leftarrow dp(l,r)+\sum_{p=l+1}^{r-1} g(l,p) \times dp(l+1,p-1) \times dp(p+1,r)\)。

举个例子来更好地了解这个过程。

拿样例 \(1\) 来解释。

在计算 \(dp(1,6)\) 时,只有 \(p=2\) 对其产生了贡献,而 \(p=4\) 时,\(dp(2,3)=0\) 故并没有产生贡献。

实现

实现有一个细节,就是答案大于等于 \(10^5\) 时,需要补上前导 \(0\)。

#include<bits/stdc++.h>

#define int long long
#define RI register int
#define ll long long

using namespace std;

namespace IO{
	inline int read(){
		RI X=0, W=0;register char ch=getchar();
		while(!isdigit(ch)) W|=ch=='-', ch=getchar();
		while(isdigit(ch)) X=(X<<1)+(X<<3)+(ch^48), ch=getchar();
		return W?-X:X;
	}
	inline void write(int x){
		if(x<0) x=-x, putchar('-');
		if(x>9) write(x/10);
		putchar(x%10+'0');
	}
}using namespace IO;

const int MAXN = 205;
const int mod = 1e5;

int n;
int dp[MAXN][MAXN];
int br[MAXN];

bool mark[MAXN][MAXN];

char s[MAXN];

inline int match(int x, int y){
	if(br[x]==0 && br[y]>0) return 1;
	if(br[y]==0 && br[x]<0) return 1;
	if(br[x]<0 && br[x]+br[y]==0) return 1;
	if(br[x]==br[y] && br[x]==0) return 3;
	return 0;
}

signed main(){
	n=read();scanf("%s",s+1);
	for(int i=1;i<=n+1;++i) dp[i][i-1]=1;
	for(int i=1;i<=n;++i){
		if(s[i]=='?') br[i]=0;
		if(s[i]=='(') br[i]=-1;
		if(s[i]==')') br[i]=1;
		if(s[i]=='[') br[i]=-2;
		if(s[i]==']') br[i]=2;
		if(s[i]=='{') br[i]=-3;
		if(s[i]=='}') br[i]=3;
	}
	for(int len=2;len<=n;len+=2){
		for(int i=1, j;i+len-1<=n;++i){
			j=i+len-1;
			dp[i][j]=dp[i+1][j-1]*match(i,j);
			if(dp[i+1][j-1]*match(i,j)) mark[i][j]|=mark[i+1][j-1];
			if(dp[i][j]>=mod) dp[i][j]-=mod;
			for(int p=i+1;p<j;p+=2){
				dp[i][j]+=(1ll*dp[i+1][p-1]*dp[p+1][j]*
				match(i,p));
				if(1ll*dp[i+1][p-1]*dp[p+1][j]*match(i,p)) mark[i][j]|=mark[i+1][p-1]|mark[p+1][j];
				if(dp[i][j]>=mod) mark[i][j]=1, dp[i][j]%=mod;
			} 
		}
	}
	if(mark[1][n]){
		int tot=0, ans[20];
		while(dp[1][n]) ans[++tot]=dp[1][n]%10, dp[1][n]/=10;
		for(int i=5;i>tot;--i) write(0);
		for(int i=tot;i>=1;--i) write(ans[i]);
		putchar(10);
	}
	else write(dp[1][n]);
	return 0;
}

标签:texttt,int,题解,COCI2007,括号,MAXN,序列,2008,dp
From: https://www.cnblogs.com/OccasionalDreamer/p/18012072

相关文章

  • CF1735D Meta-set 题解
    题目大意给定\(n\)张卡牌,每张卡牌有\(k\)个属性,第\(i\)张卡牌的第\(j\)个属性为\(c_{i,j}\)。一个由\(3\)张卡牌\(x,y,z\)组成的集合被称作好的,当且仅当对于\(1\leqi\leqk\)均有\(c_{x,i}=c_{y,i}=c_{z,i}\)或者\(c_{x,i},c_{y,i},c_{z,i}\)两两不相等。......
  • CF1793E Velepin and Marketing 题解
    题目大意有\(n\)个读者,第\(i\)年他们要一起读\(k_i\)本书,每一本书至少要让一个人读,每一个人也只能读恰好一本书。如果某一个人\(j\),如果有\(a_j\)个人这一年里和他读了同一本书,那么他就会感到满足。对于所有的\(q\)组询问,每组给定一个\(k_i\),求感到满足的人数的最......
  • CF1735E House Planning 题解
    题目大意一条直线上有\(n\)个房子和两个人,房子的坐标\(d_1,d_2,d_3\dotsd_n\),以及两个人坐标为\(p_1,p_2\)。现在会告诉你两个集合\(S_1=\{|p_1-d_i|,1\leqi\leqn\}\)以及\(S_2=\{|p_2-d_i|,1\leqi\leqn\}\)。这个写法可能不是很规范,但为了美观就写成这样了。......
  • CF1847E Triangle Platinum? 题解
    感谢@swiftc管理反馈的信息,对于题目大意确定的东西进行了完善。交互题。题目大意有一个长度为\(n\)的序列\(a\)满足\(1\leqa_i\leq4\),现在你可以进行不超过\(5500\)次询问,每次询问询问三个数\(1\leqi<j<k\leqn\),你将会得到\(a_i,a_j,a_k\)构成的三角形......
  • [ABC327G] Many Good Tuple Problems 题解
    Description对于一对长度均为\(M\)且元素值在\(\left[1,N\right]\)之间的序列\((S,T)\),定义其为好的当且仅当:存在一个长度为\(N\)的\(01\)序列\(X\),使得其满足如下条件:对于任意\(i\in\left[1,M\right]\),有\(X_{S_i}\neqX_{T_i}\)。给定\(N,M\),求在......
  • CF1918G Permutation of Given 题解
    总体思路本题通过每次在已知序列中加入\(2\)个元素的方法,可以构造出满足条件的序列\(A\),这里提供一种新的构造方法。性质因为序列\(A\)中所有元素构成的可重集与序列\(B\)中所有元素构成的可重集完全相等,所以\(A\)中所有元素之和与\(B\)中所有元素之和相等。\[\s......
  • SP277 CTGAME - City Game 题解
    题目传送门前置知识单调栈解法令\(f_{i,j}(1\lei\len,1\lej\lem)\)表示从\((1,j)\)到\((i,j)\)中以\((i,j)\)结尾的均为F的子串长度,即\((i,j)\)上面可延伸的最大距离(子矩形的长)。用单调栈的第一维存储子矩形的长,第二维存储子矩形的宽。考虑依次枚举每一......
  • qoj8171 Cola 题解
    题目链接点击打开链接题目解法很牛的题!!!会不了一点令\(pref_i\)表示第\(i\)轮知道了前缀\([1,...,i]\)考虑怎样的\(pref\)序列是合法的(即采用最优策略):\(pref_0=0\)\(\forall_{i\in[0,n-1]}\;pref_i\lepref_{i+1}\)\(pref\)中\(x\)的出现次数\(\len-x-1\),因......
  • [AGC021E] Ball Eat Chameleons 题解
    Description有\(n\)只变色龙,一开始都是蓝色。现在你喂了\(k\)次球,每次指定一只变色龙吃下你指定颜色的球。一只变色龙从蓝色变成红色当且仅当它吃的红球比蓝球多;一只变色龙从红色变成蓝色当且仅当它吃的蓝球比红球多。求最后能使所有变色龙都变成红色的方案数。两个方案......
  • AT_abc270_g [ABC270G] Sequence in mod P 题解
    题目传送门前置知识大步小步算法解法递推式为\(x_{n}=(ax_{n-1}+b)\bmodp\),发现可以统一消去\(\bmodp\),只在最后参与计算。以下过程省去模运算。当\(x_{0}=t\)时,则\(n=0\)即为所求。当\(a=0,x_{0}\net\)时,递推式转化为\(x_{n}=b\bmodp\)。若\(b=t\),则......