开O2会RE,不开就能AC
//
#include <bits/stdc++.h>
#define int long long
#define pp pair<int, int>
#define ppp pair<pair<int, int>, int>
#define pppp pair<pair<int, int>, pair<int, int> >
#define p_q priority_queue
#define gvi int, vector<int>, greater<int>
#define gvp pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> >
using namespace std;
void fast(){ ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); }
int min(int x, int y){ return x < y ? x : y; }
int max(int x, int y){ return x > y ? x : y; }
const int INF=0x3f3f3f3f, M=13, MOD=1e8;
int n, m, t, in, in1, in2, in3, sum, tmp, idx, flg, ans;
int g[M][M]; //描述草地能否种草
int a[1<<M]; //存每个合法状态的草地数
int f[M][1<<M][M*M]; //i存第几行,j存本行状态,k存草地数
vector<int> ok[M]; //存每一列的合法状态
void init(){ //init_ok 判左右相邻的合法
f[0][0][0]=1;
for (int i=0; i<(1<<m); i++){ //遍历状态
if (i&(i<<1)) continue;
if (i&(i>>1)) continue;
for (int j=0; j<=n; j++){ //遍历每一行
for (int k=0; k<m; k++){
if (i&(1<<k) && g[j][k] == 0){
flg=1;
continue;
}
}
if (flg){ flg=0; continue; }
ok[j].emplace_back(i);
}
for (int j=0; j<m; j++) a[i]+=(i>>j)&1;
}
return ;
}
signed main(){
fast();
cin >> n >> m; //n为列长,m为行
for (int i=1; i<=n; i++) for (int j=0; j<m; j++){
cin >> in, g[i][j]=in, sum+=in;
}
init();
for (int i=1; i<=n+1; i++){ //遍历列数
for (auto j:ok[i]){ //遍历当前行状态
for (auto k:ok[i-1]){ //遍历上一行状态
if (j & k) continue; //判上下冲突
for (int num=0; num<=sum; num++){ //遍历草地总数
if (num - a[j] < 0) continue; //判草地数合法
f[i][j][num]+=f[i-1][k][num-a[j]];
f[i][j][num]%=MOD;
}
}
}
}
for (int i=0; i<=sum; i++){
for (auto j:ok[n]){
ans+=f[n][j][i];
ans%=MOD;
}
}
cout << ans;
return 0;
}