Description

括号序列与猪猪侠又大战了起来。

众所周知,括号序列是一个只有(和)组成的序列,我们称一个括号序列S合法,当且仅当:

1.( )是一个合法的括号序列。

2.若A是合法的括号序列,则(A)是合法的括号序列。

3.若A,B是合法的括号序列,则AB是合法的括号序列。

我们考虑match[i]表示从左往右数第i个左括号所对应的是第几个右括号,现在他得到了一个长度为2n的括号序列,给了你m个信息,第i个信息形如ai,bi,表示match[ai]<match[bi],要你还原这个序列。

但是你发现这个猪猪侠告诉你的信息,可能有多个括号序列合法;甚至有可能告诉你一个不存在合法括号序列的信息!

你最近学了取模运算,你想知道答案对998244353(7172^23+1)取模的结果,这个模数是一个质数。

Input

第一行一个正整数T,T< = 5,表示数据组数。

对于每组数据,第一行一个n,m,n表示有几个左括号,m表示信息数。

接下来m行,每行两个数ai,bi,1< = ai,bi< = n。

Output

对于每组数据,输出一个数表示答案。

Sample Input

5

1 0

5 0

3 2

1 2

2 3

3 2

2 1

2 3

3 3

1 2

2 3

3 1

Sample Output

1

42

1

2

0

HINT

对于前两个点,是卡特兰数的情况。

对于第三个点,合法的情况只可能是 ()()()。

对于第四个点,合法情况可能是 (()()) 或者 (())()

对于第五个点,由于拓扑关系形成了环,显然无解。

对于 100% 的数据,保证 n < = 300


思路

考虑区间DP

\(dp_{l,r}\)表示满足\([l,r]\)的左区间满足条件的方案数

然后你每次考虑在\([l+1,r]\)的个区间中加入l这个括号

有三种情况:

  1. 全部包含后面
  2. 和后面相离
  3. 把后面分成两半

然后发现我们要处理出两个区间分离没有任何冲突的方案数

这个东西可以对match的二维矩阵做一个前缀和sum

然后\([l_1,r_1]\)\([l_2,r_2]\)的冲突个数就是\(l_1,r_1\)~\(l_2, r_2\)子矩阵的和


#include<bits/stdc++.h>
using namespace std;
const int N = 310;
const int Mod = 998244353;
int f[N][N], p[N][N], q[N][N], sum[N][N];
int a[N][N], b[N][N];
int n, m; int add(int a, int b) {
return (a += b) >= Mod ? a - Mod : a;
} int mul(int a, int b) {
return 1ll * a * b % Mod;
} int calc(int x1, int y1, int x2, int y2) {
return sum[x2][y2] - sum[x1 - 1][y2] - sum[x2][y1 - 1] + sum[x1 - 1][y1 - 1];
} void solve() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
f[i][j] = sum[i][j] = 0;
bool bk = 0;
for (int i = 1; i <= m; i++) {
int x, y; scanf("%d %d", &x, &y);
sum[x][y] = 1;
if (x == y) bk = 1;
}
if (bk) {
printf("0\n");
return;
}
for (int i = 1; i <= n; i++) {
f[i][i] = 1;
for (int j = 1; j <= n; j++) {
sum[i][j] += sum[i][j - 1] + sum[i - 1][j] - sum[i - 1][j - 1];
}
}
for (int len = 2; len <= n; len++) {
for (int l = 1; l + len - 1 <= n; l++) {
int r = l + len - 1;
if (!calc(l, l + 1, l, r)) f[l][r] = add(f[l][r], f[l + 1][r]);
if (!calc(l + 1, l, r, l)) f[l][r] = add(f[l][r], f[l + 1][r]);
for (int k = l + 1; k <= r - 1; k++) {
if (!calc(l, l + 1, l, k) && !calc(k + 1, l, r, k))
f[l][r] = add(f[l][r], mul(f[l + 1][k], f[k + 1][r]));
}
}
}
printf("%d\n", f[1][n]);
}
int main() {
#ifdef dream_maker
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
int T; scanf("%d", &T);
while (T--) solve();
return 0;
}

BZOJ4350: 括号序列再战猪猪侠【区间DP】的更多相关文章

  1. 2018.10.25 bzoj4350: 括号序列再战猪猪侠(区间dp)

    传送门 区间dp好题. 首先我们并不用把右括号拿进来一起dpdpdp,而是直接用左括号来dpdpdp. 然后定义状态fi,jf_{i,j}fi,j​表示区间[l,r][l,r][l,r]的合法方案数. ...

  2. BZOJ4350: 括号序列再战猪猪侠

    Description 括号序列与猪猪侠又大战了起来. 众所周知,括号序列是一个只有(和)组成的序列,我们称一个括号 序列S合法,当且仅当: 1.( )是一个合法的括号序列. 2.若A是合法的括号序列 ...

  3. [BZOJ 4350]括号序列再战猪猪侠 题解(区间DP)

    [BZOJ 4350]括号序列再战猪猪侠 Description 括号序列与猪猪侠又大战了起来. 众所周知,括号序列是一个只有(和)组成的序列,我们称一个括号 序列S合法,当且仅当: 1.( )是一个 ...

  4. UVA1626 括号序列 Brackets sequence(区间dp)

    题目传送门(洛谷)   题目传送门(UVA) 解题思路 很显然是一个区间dp,当然记忆化搜索完全可以AC,这里说一下区间dp. 区间dp的重要特征就是需要枚举中间节点k 看一看这道题,用f[i][j] ...

  5. NYOJ15|括号匹配(二)|区间DP|Elena

    括号匹配(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:6   描述 给你一个字符串,里面只包含"(",")","[&qu ...

  6. 「LuoguP1430」 序列取数(区间dp

    题目描述 给定一个长为n的整数序列(n<=1000),由A和B轮流取数(A先取).每个人可从序列的左端或右端取若干个数(至少一个),但不能两端都取.所有数都被取走后,两人分别统计所取数的和作为各 ...

  7. 区间dp提升复习

    区间\(dp\)提升复习 不得不说这波题真的不简单... 技巧总结: 1.有时候转移可以利用背包累和 2.如果遇到类似区间添加限制的题可以直接把限制扔在区间上,每次只考虑\([l,r]\)被\([i, ...

  8. 浅谈区间DP的解题时常见思路

    一.区间DP解题时常见思路 如果题目中答案满足: 大的区间的答案可以由小的区间答案组合或加减得到 大的范围可以由小的范围代表 数据范围较小 我们这时可以考虑采用区间DP来解决. 那么常见的解法有两种: ...

  9. HDU 1141---Brackets Sequence(区间DP)

    题目链接 http://poj.org/problem?id=1141 Description Let us define a regular brackets sequence in the fol ...

随机推荐

  1. C++类型前置声明

    前言 本文总结了c++中前置声明的写法及注意事项,列举了哪些情况可以用前置声明来降低编译依赖. 前置声明的概念 前置声明:(forward declaration), 跟普通的声明一样,就是个声明, ...

  2. 运行javac 报告javac不是内部或外部命令,但是运行java、java-version正常

    以前装jdk 从来没遇到过今天这种情况,各种解决办法试了一下午,终于出来了,说一下解决的办法: JAVA_HOME .classpath 都在系统变量中建立好: java_home 添加jdk的安装目 ...

  3. zw版【转发·台湾nvp系列Delphi例程】HALCON SqrtImage

    zw版[转发·台湾nvp系列Delphi例程]HALCON SqrtImageHALCON SqrtImage 範例 (RAD Studio XE Delphi x64) zw版[转发·台湾nvp系列 ...

  4. 20154312曾林 - Exp1 PC平台逆向破解

    1.逆向及Bof基础实践说明 1.1-实践目标 对象:pwn1(linux可执行文件) 目标:使程序执行另一个代码片段:getshell 内容: 手工修改可执行文件,改变程序执行流程,直接跳转到get ...

  5. flex与j2ee的结合(flex+Spring)

    分类: flex spring2012-04-25 02:11 1262人阅读 评论(1) 收藏 举报 flexspringactionscriptjavapropertiesservlet   目录 ...

  6. Linux学习笔记之Centos7设置Linux静态IP

    ***如下资料源自互联网*** 这里以CentOS 7系列为例设置静态IP,原来RedHat系列的Linux发行版可以通过setup工具方便的设置静态IP,但是在版本7之后setup工具的功能就逐渐减 ...

  7. Stitching模块中focalsFromHomography初步研究

    在Stitching模块中,通过“光束法平差”的时候,有一个步骤为“通过单应矩阵估算摄像头焦距”,调用的地方为:   , ));    ] ];    d2 ] ]) ] ]);    v1 ] ]  ...

  8. 20145325张梓靖 《Java程序设计》第2周学习总结

    20145325张梓靖 <Java程序设计>第2周学习总结 教材学习内容总结 整数 short 2字节,int 4字节,long 8字节 字节 byte 1字节 浮点数 float 4字节 ...

  9. Michael-Scott非阻塞队列(lock-free)算法的C实现

    Michael-Scott非阻塞队列算法,即MS-queue算法,是1 9 9 6 年由Maged . M .Michael and M. L. Scott提出的,是最为经典的并发FIFO队列上的算法 ...

  10. 同样的输入,为什么Objects.hash()方法返回的hash值每次不一样?

    背景 开发过程中发现一个问题,项目中用Set保存AopMethod对象用于去重,但是发现即使往set中添加相同内容的对象,每次也能够添加成功. AopMethod类的部分代码如下: public cl ...