1. 程式人生 > >Bzoj4350 括號序列再戰豬豬俠

Bzoj4350 括號序列再戰豬豬俠

決策 char ast fin string 個數 class oid 卡特蘭數

Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 97 Solved: 44

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

動態規劃 區間DP 腦洞題

這兩個家夥怎麽打起來沒完沒了……

既然求方案數,那就愉快地DP吧。

考慮可能會有哪些情況:

只依據左括號進行決策,不表示出右括號,設f[i][j]為第i個到第j個左括號(和它們的右括號)構成的括號序列的方案數。

設last為一個已有的完整括號序列,新加入一對括號,可能有三種情況:

1、(last) 這要求從 i+1 到 j 範圍內沒有“右括號在 i 後面”的限制條件

2、()last 這要求從i+1 到 j 範圍內沒有 “右括號在 i 前面”的限制條件

3、( la ) st 枚舉區間斷點k,分別滿足上面的條件

討論三種情況進行轉移即可。

註意特判有自環的情況。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #define LL long long
 7 using namespace std;
 8 const int mod=998244353;
 9 const int mxn=305;
10 int read(){
11     int x=0,f=1;char ch=getchar();
12     while(ch<0 || ch>9){if(ch==-)f=-1;ch=getchar();}
13     while(ch>=0 && ch<=9){x=x*10+ch-0;ch=getchar();}
14     return x*f;
15 }
16 int S[mxn][mxn],mp[mxn][mxn];
17 int f[mxn][mxn];
18 int n,m;
19 void init(){
20     memset(S,0,sizeof S);
21     memset(mp,0,sizeof mp);
22     memset(f,0,sizeof f);
23     return;
24 }
25 int s(int x1,int y1,int x2,int y2){
26     return S[x2][y2]-S[x1-1][y2]-S[x2][y1-1]+S[x1-1][y1-1];
27 }
28 int main(){
29     int i,j,u,v;
30     int T=read();
31     while(T--){
32         init();
33         n=read();m=read();
34         bool flag=0;
35         for(i=1;i<=m;i++){
36             u=read();v=read();
37             mp[u][v]=1;
38             if(u==v)flag=1;
39         }
40         if(flag){puts("0");continue;}
41         for(i=1;i<=n;i++)
42             for(j=1;j<=n;j++)
43                 S[i][j]=S[i][j-1]+mp[i][j];
44         for(i=1;i<=n;i++)
45             for(j=1;j<=n;j++)
46                 S[i][j]+=S[i-1][j];
47         //
48         for(i=1;i<=n;i++)f[i][i]=1;
49         for(int st=2;st<=n;st++){
50             for(i=1;i+st-1<=n;i++){
51                 j=i+st-1;
52                 if(!s(i,i+1,i,j))f[i][j]=(f[i][j]+f[i+1][j])%mod;// ( last )
53                 if(!s(i+1,i,j,i))f[i][j]=(f[i][j]+f[i+1][j])%mod;// ()last
54                 for(int k=i+1;k<j;k++){ //(la)st
55                     if(!s(i,i+1,i,k) && !s(k+1,i,j,k)){
56                         f[i][j]=((LL)f[i][j]+(LL)f[i+1][k]*f[k+1][j]%mod)%mod;
57                     }
58                 }
59             }
60         }
61         printf("%d\n",f[1][n]);
62     }
63     return 0;
64 }

Bzoj4350 括號序列再戰豬豬俠