// opt(x, y, r) // x, y: coordinate // r: how far is it from 4 int n, m, a[MAX_N][MAX_N], in_deg[MAX_N][MAX_N], opt[MAX_N][MAX_N][4], ans; char tag[MAX_N][MAX_N]; Status sorted[MAX_N * MAX_N];
boolis_valid(int x, int y){ return x >= 0 && x < n && y >= 0 && y < m; }
voidcalculate_in_deg(){ // edge: x -> x + 1 for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { for (int k = 0; k < 4; ++k) { int nx = i + dx[k], ny = j + dy[k]; if (is_valid(nx, ny) && a[nx][ny] + 1 == a[i][j]) { ++in_deg[i][j]; } } } } }
queue<Status> q; voidtopological_sort(){ for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { if (in_deg[i][j] == 0) { q.push({i, j}); tag[i][j] = 'S'; } } }
int sorted_ptr = 0; while (!q.empty()) { auto f = q.front(); q.pop(); sorted[sorted_ptr++] = f;
int nex_cnt = 0; for (int i = 0; i < 4; ++i) { int nx = f.x + dx[i], ny = f.y + dy[i]; if (is_valid(nx, ny) && a[nx][ny] == a[f.x][f.y] + 1) { ++nex_cnt; } if (is_valid(nx, ny) && a[nx][ny] == a[f.x][f.y] + 1 && (--in_deg[nx][ny]) == 0) { q.push({nx, ny}); } }
if (nex_cnt == 0) { tag[f.x][f.y] = 'T'; } } }
voidcalculate(){ int tot = n * m; for (int i = 0; i < tot; ++i) { int x = sorted[i].x, y = sorted[i].y; if (tag[x][y] == 'S') { opt[x][y][3] = 1; continue; }
for (int k = 0; k < 4; ++k) { int pre_x = x + dx[k], pre_y = y + dy[k]; if (is_valid(pre_x, pre_y) && a[pre_x][pre_y] + 1 == a[x][y]) { for (int r = 2; r >= 0; --r) { opt[x][y][r] = (opt[pre_x][pre_y][r + 1] + opt[x][y][r]) % P; } opt[x][y][0] = (opt[pre_x][pre_y][0] + opt[x][y][0]) % P; } }
if (tag[x][y] == 'T') { ans = (ans + opt[x][y][0]) % P; } } }
intmain(){ scanf("%d%d", &n, &m); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { scanf("%d", &a[i][j]); } }