bzoj4350: 括号序列再战猪猪侠

4350: 括号序列再战猪猪侠

链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4350

Time Limit: 20 Sec  Memory Limit: 512 MB

Description

括号序列与猪猪侠又大战了起来。
众所周知,括号序列是一个只有(和)组成的序列,我们称一个括号
序列S合法,当且仅当:
1.( )是一个合法的括号序列。
2.若A是合法的括号序列,则(A)是合法的括号序列。
3.若A,B是合法的括号序列,则AB是合法的括号序列。
我们考虑match[i]表示从左往右数第i个左括号所对应的是第几个右
括号,现在他得到了一个长度为2n的括号序列,给了你m个信息,第i
个信息形如ai,bi,表示match[ai]<match[bi],要你还原这个序列。
但是你发现这个猪猪侠告诉你的信息,可能有多个括号序列合法;甚
至有可能告诉你一个不存在合法括号序列的信息!
你最近学了取模运算,你想知道答案对998244353(7*17*2^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
题解:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int M = 305;
const ll mod = 998244353;
ll dp[M][M];
int s[M][M];
void init(){
    memset(dp, 0, sizeof(dp));
    memset(s, 0, sizeof(s));
}
int check(int a, int b, int c, int d){
    return s[c][d] - s[a - 1][d] - s[c][b - 1] + s[a - 1][b - 1];
}
inline ll moc(ll a){return a > mod ? a - mod : a;}
int main()
{
     
    int T;
    scanf("%d", &T);
    while(T--){
        int n, m, a, b, fg = 0;
        scanf("%d%d", &n, &m);
        init();
        for(int i = 1; i <= m; i++){
            scanf("%d%d", &a, &b);s[a][b] = 1;
        }
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
        for(int i = 1; i <= n; i++) 
            if(check(i, i, i, i)){
                puts("0");fg = 1;break;
            }
        if(fg)continue;
        for(int i = 1; i <= n; i++)dp[i][i] = 1;
        for(int len = 2; len <= n; len++){
            for(int i = 1; i <= n - len + 1; i++){
                int j = i + len - 1;
                if(!check(i, i+1, i, j)) dp[i][j] = moc(dp[i][j] + dp[i + 1][j]);
                if(!check(i+1, i, j, i)) dp[i][j] = moc(dp[i][j] + dp[i + 1][j]);
                for(int k = i + 1; k < j; k++)   
                if(!check(i, i+1, i, k) && ! check(k + 1, i, j, k))
                dp[i][j] = moc(dp[i][j] + dp[i + 1][k] * dp[k + 1][j] % mod);
            }
        }
        printf("%lld\n", dp[1][n]); 
    }
    return 0;
}
View Code

 

posted @ 2022-11-29 21:23  Ed_Sheeran  阅读(27)  评论(0编辑  收藏  举报