首页 > [dp] Jzoj P5804 简单的序列

[dp] Jzoj P5804 简单的序列

Description

从前有个括号序列 s,满足 |s| = m。你需要统计括号序列对 (p, q) 的数量。

其中 (p, q) 满足 |p| + |s| + |q| = n,且 p + s + q 是一个合法的括号序列。

Input

从文件 bracket.in 中读入数据。第一行两个正整数 n, m。

第二行一个长度为 m 的括号序列,表示 s。

 

Output

输出到文件 bracket.out 中。

输出一行一个整数,表示符合条件的 (p, q) 的数量对 10^9 + 7 取模的值。

 

 

Sample Input

【样例 1 输入】
4 1 (
【样例 2 输入】
4 4 (())
【样例 3 输入
4 3 (((

Sample Output

【样例 1 输出】
4
【样例 2 输出】
1
【样例 3 输出】
0

Data Constraint

对于 10% 的数据,n ≤ 20;

对于 25% 的数据,n ≤ 200;

对于另外 5% 的数据,n = m;

对于 55% 的数据,n − m ≤ 200;

对于 100% 的数据,1 ≤ m ≤ n ≤ 10^5, n − m ≤ 2000。

 

题解

  • 我们可以把左括号看成+1,右括号看成-1
  • 那么一个合法的括号序列就是左括号>=右括号
  • 设f[i][j]为长度为i的序列 左括号比右括号多j个 的方案数
  • 状态转移方程明显就是:f[i-1][j-1]+f[i-1][j+1]
  • 那么考虑如何求最终的方案数
  • 首先要满足左括号多于右括号,和 |p| + |s| + |q| = n
  • 每次枚举一个i表示前面的p序列的长度,再枚举一个j表示p序列左括号比右括号多的个数
  • 那么就是f[i][j]*f[n-m-i][j+tot](tot为原来序列中左括号比右括号多的个数)

代码

 1 #include 
 2 #include 
 3 #include 
 4 #include 
 5 using namespace std;
 6 const long long mo=1e9+7;
 7 int n,m,tot,ltot;
 8 char s[100010];
 9 long long ans,f[2010][2010];
10 int main()
11 {
12     freopen("bracket.in","r",stdin);
13     freopen("bracket.out","w",stdout);
14     scanf("%d%d",&n,&m);
15     scanf("%s",s);
16     for (int i=0;i)
17     {
18         if (s[i]=='(') tot++; else tot--;
19         if (i==0) ltot=tot; else ltot=min(tot,ltot);
20     }
21     f[0][0]=1;
22     for (int i=1;i<=n-m;i++)
23         for (int j=0;j<=i;j++)
24             if (j==0) f[i][j]=f[i-1][j+1];
25             else f[i][j]=(f[i-1][j-1]+f[i-1][j+1])%mo;
26     for (int i=0;i<=n-m;i++)
27         for (int j=0;j<=i;j++)
28             if (j+tot<=n-m&&j+ltot>=0)
29                 (ans+=f[i][j]*f[n-m-i][j+tot])%=mo;
30     printf("%lld",ans);
31     return 0;
32 }

 

转载于:https://www.cnblogs.com/Comfortable/p/9464185.html

更多相关:

  • 已知n组括号,开发一个程序,生成这n组括号所有的合法的组合可能。 例如:n = 3 结果为: ["((()))", “(()())”, “(())()”, “()(())”, “()()()”] 首先思考如何生成所有的括号组合的可能性,即例如2组括号,总共4个符号组合的可能型,那么每个位置就有两种括号的可能性,要么左括号,要么右括号...

  • 为避免浏览多个作者参与编写的项目时,因风格的不同造成不便时,大家可以使用同一套风格规范来统一标准 代码必须遵循PSR1的规范缩进使用4个空格,而不是TAB键缩进每行代码控制在80-120个每个namespace申明语句后,每个'use'申明语句块后一定要空一行类的开始和结束花括号必须自成一行,方法的也是类的属性必须添加访问控制修饰...

  • 题目:栈的压入、弹出序列 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。 示例 1:...

  • 简单版 @for $i from 1 through 6 {&:nth-of-type(#{$i}) img {transition-delay: calc(0.1 *#{$i}s);//逐次延时效果} } 进阶版 @for $i from 1 through length($数组) {$color: nth($数组, $i);...

  • Gold Code Gold Code是以Robert Gold的名字命名的。它是一组特殊的二进制随机(伪随机)序列,其中成员序列之间的相关性很小。由于这种特性(较小的相关性),它被广泛地用作各种无线通信系统的扰码。 我们可以非常简单地利用 m序列 来生成Gold Code: 选择两个m序列,且这两个序列的移位寄存器的数量相同,然...

  • 翻译自:sharetechnote: LFSR LFSR Linear Feedback Shift Register - 线性反馈移位寄存器 LFSR 是一种移位寄存器电路,其中两个或多个中间步骤的输出线性组合并反馈到输入值,这就是为什么它被称为线性反馈移位寄存器的原因。 该电路具有以下特点: 如果初始状态相同,则最终会得到...

  • 如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。 例如, [1,7,4,9,2,5] 是一个摆动序列,因为差值 (6,-3,5,-7,3) 是正负交替出现的。相反, [1,4,7,2,5] 和 [1,7,4,5,5] 不是摆动序列,第一...

  •         Apache POI是一个开源的利用Java读写Excel,WORD等微软OLE2组件文档的项目。        我的需求是对Excel的数据进行导入或将数据以Excel的形式导出。先上简单的测试代码:package com.xing.studyTest.poi;import java.io.FileInputSt...

  • 要取得[a,b)的随机整数,使用(rand() % (b-a))+ a; 要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a; 要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1; 通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。 要取得a到b之间的...

  • 利用本征图像分解(Intrinsic Image Decomposition)算法,将图像分解为shading(illumination) image 和 reflectance(albedo) image,计算图像的reflectance image。 Reflectance Image 是指在变化的光照条件下能够维持不变的图像部分...

  • 题目:面试题39. 数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输出: 2 限制: 1 <= 数组长度 <= 50000 解题: cl...

  • 题目:二叉搜索树的后序遍历序列 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。 参考以下这颗二叉搜索树:      5     /    2   6   /  1   3示例 1: 输入: [1,6,3,2,5] 输出...