#include #include #include #include #include #include #include #include #include #include #include #include #include #define repd(i,a,b) for (int i=(a);i<(b);i++) #define rep(i,n) repd(i,0,n) #define var auto #define mod 1000000007 #define inf 2147483647 #define nil -1 typedef long long ll; using namespace std; int input(){ int a; cin >> a; return a; } template void output(T a, int p) { if(p){ cout << fixed << setprecision(p) << a << "\n"; } else{ cout << a << "\n"; } } // end of template int main() { cin.tie(0); // source code int H = input(); int W = input(); vector> cell(H, vector (W, -1)); rep(i, H){ rep(j, W){ char c; cin >> c; if (c == '0') cell[i][j] = 0; if (c == '1') cell[i][j] = 1; } } // 0101010101... or ...11..., ...00... vector dpc[2]; // judge if the cell of the first row must be 0 or 1 rep(i, 2){ dpc[i].resize(W, 0); } ll ret = 1; rep(i, H){ rep(j, W){ if (cell[i][j] != -1) { dpc[(i + cell[i][j]) % 2][j] = 1; } } } rep(i, W){ if (!dpc[0][i] && !dpc[1][i]) { ret *= 2; } else if (dpc[0][i] && dpc[1][i]){ ret = 0; } ret %= mod; } bool is01 = true; bool is10 = true; if (ret) { rep(i, W){ if (dpc[(i + 1) % 2][i]) { is01 = false; } if (dpc[i % 2][i]) { is10 = false; } } } vector dpr[2]; rep(i, 2){ dpr[i].resize(H, 0); } rep(i, H){ rep(j, W){ if (cell[i][j] != -1) { dpr[(j + cell[i][j]) % 2][i] = 1; } } } ll ret01 = (is01 && !dpr[1][0]) ? 1 : 0; ll ret10 = (is10 && !dpr[0][0]) ? 1 : 0; repd(i, 1, H){ if (!dpr[0][i] && !dpr[1][i]) { ret01 *= 2; ret10 *= 2; ret01 %= mod; ret10 %= mod; } else if(dpr[0][i] && dpr[1][i]){ ret01 = 0; ret10 = 0; } } ret = (ret ? ret + (is01 ? ret01 - 1 : 0) + (is10 ? ret10 - 1 : 0) : 0); ret += mod; ret %= mod; output(ret, 0); return 0; }