[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 }
View Code

 

posted @ 2022-04-25 14:17  PYWBKTDA  阅读(137)  评论(0编辑  收藏  举报