如果 opt=1,那么我们考虑 (x,y) 的上一格和下一格的前(后)缀状态,发现它们的第 y 个插头和插头 t 都必须为 0,其他插头的状态必须对应相等。(可以理解为把两个长方形融合成一个,或者选择断开)
```cpp
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=17,MOD=998244353;
int T,n,m,a[N][N],f[N][N][1<<15][2],g[N][N][1<<15][2],ans[1007];
struct query{int op,x,y,t;}q[1007];
void add(int& x,int y){x+=y;if (x>=MOD) x-=MOD;}
void solve(){
memset(f,0,sizeof(f));memset(g,0,sizeof(g));
f[0][m][0][0]=1;
for (int i=1;i<=n;++i) for (int j=1;j<=m;++j){
auto now=f[i][j],pre=(j==1?f[i-1][m]:f[i][j-1]);
for (int s=0;s<(1<<m);++s) for (int t=0;t<2;++t) if (pre[s][t]){
if (t&&((s>>j-1)&1)) continue;
int tmp=pre[s][t];
if (!a[i][j]){
if (t||((s>>j-1)&1)) continue;
add(now[s][t],tmp);
continue;
}
if (t){
if (j<m&&!((s>>j)&1)&&a[i][j+1]) add(now[s][t],tmp);
add(now[s][0],tmp);
}
else if ((s>>j-1)&1){
if (i<n&&a[i+1][j]) add(now[s][t],tmp);
add(now[s^(1<<j-1)][t],tmp);
}
else{
add(now[s][0],tmp);
if (i<n&&a[i+1][j]) add(now[s|(1<<j-1)][0],tmp);
if (j<m&&!((s>>j)&1)&&a[i][j+1]) add(now[s][1],tmp);
}
}
}
g[n+1][1][0][0]=1;
for (int i=n;i;--i) for (int j=m;j;--j){
auto now=g[i][j],pre=(j==m?g[i+1][1]:g[i][j+1]);
for (int s=0;s<(1<<m);++s) for (int t=0;t<2;++t) if (pre[s][t]){
if (t&&((s>>j-1)&1)) continue;
int tmp=pre[s][t];
if (!a[i][j]){
if (t||((s>>j-1)&1)) continue;
add(now[s][t],tmp);
continue;
}
if (t){
if (j&&!((s>>j-2)&1)&&a[i][j-1]) add(now[s][t],tmp);
add(now[s][0],tmp);
}
else if ((s>>j-1)&1){
if (i&&a[i-1][j]) add(now[s][t],tmp);
add(now[s^(1<<j-1)][t],tmp);
}
else{
add(now[s][0],tmp);
if (i&&a[i-1][j]) add(now[s|(1<<j-1)][0],tmp);
if (j&&!((s>>j-2)&1)&&a[i][j-1]) add(now[s][1],tmp);
}
}
}
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n>>m;
for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) cin>>a[i][j];
cin>>T;
for (int i=1;i<=T;++i){
cin>>q[i].op;
if (q[i].op==1) cin>>q[i].x>>q[i].y;
if (q[i].op==2) cin>>q[i].x;
if (q[i].op==3) cin>>q[i].x;
if (q[i].op==4) cin>>q[i].x>>q[i].y>>q[i].t;
if (q[i].op==5) cin>>q[i].y>>q[i].x>>q[i].t;
}
solve();
cout<<f[n][m][0][0]<<endl;
for (int i=1;i<=T;++i){
if (q[i].op==1){
int sum=0,x=q[i].x,y=q[i].y;
auto F=(y==1?f[x-1][m]:f[x][y-1]),G=(y==m?g[x+1][1]:g[x][y+1]);
int msk=((1<<m)-1)^(1<<y-1);
sum=(ll)F[0][0]*G[0][0]%MOD;
for (int s=msk;s;s=s-1&msk) sum=(sum+(ll)F[s][0]*G[s][0])%MOD;
ans[i]=sum;
}
if (q[i].op==2) ans[i]=(ll)f[q[i].x-1][m][0][0]*g[q[i].x+1][1][0][0]%MOD;
if (q[i].op==4){
int sum=0,x=q[i].x,yL=q[i].y,yR=q[i].y+q[i].t;
auto F=(yL==1?f[x-1][m]:f[x][yL-1]),G=(yR==m?g[x+1][1]:g[x][yR+1]);
int msk=((1<<m)-1)^((1<<yR)-(1<<yL-1));
sum=(ll)F[0][0]*G[0][0]%MOD;
for (int s=msk;s;s=s-1&msk) sum=(sum+(ll)F[s][0]*G[s][0])%MOD;
ans[i]=sum;
}
}
for (int i=1;i<=max(n,m);++i) for (int j=1;j<i;++j) swap(a[i][j],a[j][i]);
swap(n,m);solve();
for (int i=1;i<=T;++i){
if (q[i].op==3) ans[i]=(ll)f[q[i].x-1][m][0][0]*g[q[i].x+1][1][0][0]%MOD;
if (q[i].op==5){
int sum=0,x=q[i].x,yL=q[i].y,yR=q[i].y+q[i].t;
auto F=(yL==1?f[x-1][m]:f[x][yL-1]),G=(yR==m?g[x+1][1]:g[x][yR+1]);
int msk=((1<<m)-1)^((1<<yR)-(1<<yL-1));
sum=(ll)F[0][0]*G[0][0]%MOD;
for (int s=msk;s;s=s-1&msk) sum=(sum+(ll)F[s][0]*G[s][0])%MOD;
ans[i]=sum;
}
}
for (int i=1;i<=T;++i) cout<<ans[i]<<'\n';
return 0;
}
```