[loj2839]安全门
特判$n$为奇数的情况,显然此时答案为0
将$($和$)$分别看作$\pm 1$,记$a_{i}$为前缀和,则合法当且仅当满足以下条件——
存在$0\le l\le r\le n$(反转区间$(l,r]$,允许为空),使得$\begin{cases}a_{r}-a_{l}=\frac{a_{n}}{2}\\\forall i\in [0,l],a_{i}\ge 0\\\forall i\in (l,r],a_{i}\le 2a_{l}\\\forall i\in (r,n],a_{i}\ge a_{n}\end{cases}$
根据条件的形式,对是否存在$a_{i}<0$和$a_{i}<a_{n}$分类讨论:
1.均不存在,此时可得$0\le a_{n}\le a_{0}=0$,进而必然合法(不需要反转)
具体的,条件为$\begin{cases}\forall i\in [0,n],a_{i}\ge 0\\a_{n}=0\end{cases}$,直接dp即可,时间复杂度为$o(n^{2})$
2.恰存在一种,根据对称性不妨假设为前者,此时可得$a_{n}<0$(否则存在$a_{i}<0\le a_{n}$)
当确定$l$后,分析与$r$相关的限制,显然取$r=\min_{l\le r,a_{r}=a_{l}+\frac{a_{n}}{2}}r$,并要求$\forall i\in (l,r],a_{i}\le 2a_{l}$
性质1:记$l_{0}=\min_{a_{i}<0}i$,则$l$可以贪心取$[0,l_{0})$中$a_{l}$最大的位置
1.若$a_{l}+\frac{a_{n}}{2}\ge 0$,也即$\in [0,a_{l})$,进而根据连续性可得$r\in (l,l_{0})$
同时,对于后者的条件,有$\forall i\in (l,r],a_{i}\le a_{l}\le 2a_{l}$(显然$a_{l}\ge a_{0}=0$)
2.若$a_{l}+\frac{a_{n}}{2}<0$,假设$(l',r']$可行,则$a_{l}+\frac{a_{n}}{2}\in [a_{r'},0)$,进而可得$r\in [l_{0},r']$
同时,对于后者的条件,有$\forall i\in (l,r],a_{i}\le a_{l'}\le a_{l}$,因此$(l,r]$也可行
进一步的,对$a_{l}+\frac{a_{n}}{2}$的符号分类讨论:
(1)若$a_{l}+\frac{a_{n}}{2}\ge 0$,参考性质1的证明(第1种情况)此时必然合法
具体的,条件为$\begin{cases}\forall i\in [0,l_{0}),a_{i}\ge 0(>a_{n})\ \ \ a_{l_{0}-1}=0\ \ \ \max_{i\in [0,l_{0})}a_{i}=a_{l}\ \ \ \\\forall i\in (l_{0},n],a_{i-1}-a_{n}\ge 0\\s_{l_{0}}=')'(a_{l_{0}}=-1\ge a_{n})\ \ \ a_{i}-\frac{a_{l_{0}}-a_{n}+1}{2}\ge 0\end{cases}$
对$[0,l_{0})$枚举$a_{l}$后dp,对$(l_{0},n]$直接dp(记录$a_{i-1}-a_{n}$),最终枚举$l_{0},a_{l}$和$a_{l_{0}}-a_{n}$即可,时间复杂度为$o(n^{3})$
(2)若$a_{l}+\frac{a_{n}}{2}<0$,注意到条件$\begin{cases}a_{i}\le 2a_{l}\\a_{r}=a_{l}+\frac{a_{n}}{2}\end{cases}$可以转换为$\begin{cases}a_{i}-a_{n}\le 2(a_{l}-\frac{a_{n}}{2})\\a_{r}-a_{n}=a_{l}-\frac{a_{n}}{2}\end{cases}$
而$a_{i}-a_{n}$恰是dp时所记录的,因此与(1)类似,仅需对$(l_{0},n]$枚举$a_{l}-\frac{a_{n}}{2}$后dp,时间复杂度为$o(n^{3})$
3.均存在,类似的记$r_{0}=\max_{a_{i}<a_{n}}i$,显然$l_{0}\le r_{0}$
记$l_{1}$和$r_{1}$分别为$[0,l_{0})/[r_{0},n]$中$a_{l_{1}}/a_{r_{1}}$最大的位置,则有以下性质——
性质2:若$a_{l_{1}}+\frac{a_{n}}{2}\le a_{r_{1}}$,则$l$可以贪心取$l_{1}$
假设$(l',r']$可行,显然必要条件为$\forall i\in [l_{0},r_{0}],a_{i}\le 2a_{l'}$
考虑其中$a_{r_{0}}=a_{n}-1$,结合$a_{n}\equiv 0(mod\ 2)$可得$a_{n}\le 2a_{l'}\le 2a_{l_{1}}$
代入可得$a_{l_{1}}+\frac{a_{n}}{2}\in [a_{n},a_{r_{1}}]$,进而$\exists r\in (r_{0},r_{1}]$满足$a_{r}=a_{l_{1}}+\frac{a_{n}}{2}$,不妨取其中最小的位置
此时,将$\forall i\in (l,r],a_{i}\le 2a_{l}$的条件分为三部分,即$\begin{cases}\forall i\in (l,l_{0}),a_{i}\le a_{l_{1}}\le 2a_{l_{1}}\\\forall i\in [l_{0},r_{0}],a_{i}\le 2a_{l'}\le 2a_{l_{1}}\\\forall i\in (r_{0},r],a_{i}\le a_{l_{1}}+\frac{a_{n}}{2}\le2a_{l_{1}}\end{cases}$
(其中第3部分左边是因为$r$的最小性,右边代入$a_{n}\le 2a_{l_{1}}$可得)
同时,这也是$l$可以取$l_{1}$的必要条件,因此强制$l$取$l_{1}$即可处理此情况
此时做法即与2.(2)类似,仅需额外处理$r_{0}\le r$的限制,时间复杂度为$o(n^{3})$
当$a_{l_{1}}+\frac{a_{n}}{2}\ge a_{r_{1}}$时,同理$r$可以贪心取$r_{1}$(证明类似),并去掉恰相等的情况即可
最终,总复杂度为$o(n^{3})$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 305 4 #define mod 1000000007 5 #define ll long long 6 int n,m,ans,g[N][N],f1[N][N],f2[N][N][2],f3[N][N<<1][3]; 7 char s[N]; 8 void add(int &x,int y){ 9 x+=y;if (x>=mod)x-=mod; 10 } 11 void rev(){ 12 reverse(s+1,s+n+1); 13 for(int i=1;i<=n;i++) 14 if (s[i]!='x')s[i]='('+')'-s[i]; 15 } 16 void get_g(){ 17 for(int al=0;al<=n;al++){ 18 memset(f2,0,sizeof(f2)); 19 f2[0][0][!al]=1; 20 for(int i=1;i<=n;i++) 21 for(int j=0;j<i;j++){ 22 if ((!f2[i-1][j][0])&&(!f2[i-1][j][1]))continue; 23 if ((s[i]!=')')&&(j<al)){ 24 int j0=j+1; 25 add(f2[i][j0][j0==al],f2[i-1][j][0]); 26 add(f2[i][j0][1],f2[i-1][j][1]); 27 } 28 if ((s[i]!='(')&&(j)){ 29 int j0=j-1; 30 add(f2[i][j0][j0==al],f2[i-1][j][0]); 31 add(f2[i][j0][1],f2[i-1][j][1]); 32 } 33 } 34 for(int l0=1;l0<=n;l0++)g[l0][al]=f2[l0-1][0][1]; 35 } 36 } 37 void calc1(){ 38 f1[0][0]=1; 39 for(int i=1;i<=n;i++) 40 for(int j=0;j<i;j++){ 41 if (s[i]!=')')add(f1[i][j+1],f1[i-1][j]); 42 if ((s[i]!='(')&&(j))add(f1[i][j-1],f1[i-1][j]); 43 } 44 add(ans,f1[n][0]); 45 } 46 void calc2(){ 47 get_g(); 48 memset(f1,0,sizeof(f1)); 49 f1[n+1][0]=1; 50 for(int i=n;i;i--) 51 for(int j=0;j<=n-i;j++){ 52 if ((s[i]!=')')&&(j))add(f1[i][j-1],f1[i+1][j]); 53 if (s[i]!='(')add(f1[i][j+1],f1[i+1][j]); 54 } 55 for(int l0=1;l0<=n;l0++) 56 if (s[l0]!='('){ 57 for(int al=0;al<=n;al++) 58 for(int an=1;an<=n;an+=2) 59 if (al-(an+1>>1)>=0)ans=(ans+(ll)g[l0][al]*f1[l0+1][an])%mod; 60 } 61 for(int an=1;an<=n;an++){ 62 memset(f2,0,sizeof(f2)); 63 f2[n+1][0][0]=1; 64 for(int i=n;i;i--) 65 for(int j=0;j<=n-i;j++){ 66 if ((!f2[i+1][j][0])&&(!f2[i+1][j][1]))continue; 67 if ((s[i]!=')')&&(j)){ 68 int j0=j-1; 69 add(f2[i][j0][j0==an],f2[i+1][j][0]); 70 add(f2[i][j0][j0<=(an<<1)],f2[i+1][j][1]); 71 } 72 if (s[i]!='('){ 73 int j0=j+1; 74 add(f2[i][j0][j0==an],f2[i+1][j][0]); 75 add(f2[i][j0][j0<=(an<<1)],f2[i+1][j][1]); 76 } 77 } 78 for(int l0=1;l0<=n;l0++){ 79 if (s[l0]!='('){ 80 for(int al=0;al<=n;al++){ 81 int j=(an-al<<1)-1; 82 if (((al<<1)-an<0)&&(j<=n))ans=(ans+(ll)g[l0][al]*f2[l0+1][j][1])%mod; 83 } 84 } 85 } 86 } 87 } 88 void calc3(int P){ 89 for(int an=0;an<=n;an++){ 90 memset(f3,0,sizeof(f3)); 91 f3[n+1][n][!an]=1; 92 for(int i=n;i;i--) 93 for(int j=i-n;j<=n-i;j++){ 94 if ((!f3[i+1][j+n][0])&&(!f3[i+1][j+n][1])&&(!f3[i+1][j+n][2]))continue; 95 if ((s[i]!=')')&&(j!=-n)){ 96 int j0=j-1; 97 if (j0>=0)add(f3[i][j0+n][j0==an],f3[i+1][j+n][0]); 98 add(f3[i][j0+n][(j0<=(an<<1))+(j0<0)],f3[i+1][j+n][1]); 99 if (j0<=(an<<1))add(f3[i][j0+n][2],f3[i+1][j+n][2]); 100 } 101 if (s[i]!='('){ 102 int j0=j+1; 103 if (j0>=0)add(f3[i][j0+n][j0==an],f3[i+1][j+n][0]); 104 add(f3[i][j0+n][(j0<=(an<<1))+(j0<0)],f3[i+1][j+n][1]); 105 if (j0<=(an<<1))add(f3[i][j0+n][2],f3[i+1][j+n][2]); 106 } 107 } 108 for(int l0=1;l0<=n;l0++){ 109 if (s[l0]!='('){ 110 for(int al=0;al<=n;al++){ 111 int j=(an-al<<1)-1; 112 if (abs(j)<=n)ans=(ans+(ll)g[l0][al]*f3[l0+1][j+n][2])%mod; 113 } 114 } 115 } 116 } 117 if (P){ 118 for(int an=0;an<=n;an++){ 119 memset(f3,0,sizeof(f3)); 120 f3[n+1][n][!an]=1; 121 for(int i=n;i;i--) 122 for(int j=i-n;j<=n-i;j++){ 123 if ((!f3[i+1][j+n][0])&&(!f3[i+1][j+n][1])&&(!f3[i+1][j+n][2]))continue; 124 if ((s[i]!=')')&&(j!=-n)){ 125 int j0=j-1; 126 if (j0<=an){ 127 if (j0>=0)add(f3[i][j0+n][j0==an],f3[i+1][j+n][0]); 128 add(f3[i][j0+n][(j0<=(an<<1))+(j0<0)],f3[i+1][j+n][1]); 129 } 130 if (j0<=(an<<1))add(f3[i][j0+n][2],f3[i+1][j+n][2]); 131 } 132 if (s[i]!='('){ 133 int j0=j+1; 134 if (j0<=an){ 135 if (j0>=0)add(f3[i][j0+n][j0==an],f3[i+1][j+n][0]); 136 add(f3[i][j0+n][(j0<=(an<<1))+(j0<0)],f3[i+1][j+n][1]); 137 } 138 if (j0<=(an<<1))add(f3[i][j0+n][2],f3[i+1][j+n][2]); 139 } 140 } 141 for(int l0=1;l0<=n;l0++){ 142 if (s[l0]!='('){ 143 for(int al=0;al<=n;al++){ 144 int j=(an-al<<1)-1; 145 if (abs(j)<=n)ans=(ans-(ll)g[l0][al]*f3[l0+1][j+n][2]%mod+mod)%mod; 146 } 147 } 148 } 149 } 150 } 151 } 152 int main(){ 153 scanf("%d%s",&n,s+1); 154 if (n&1)printf("0\n"); 155 else{ 156 calc1(),calc2(),calc3(0),rev(),calc2(),calc3(1); 157 printf("%d\n",ans); 158 } 159 return 0; 160 }