【题目链接】
【思路要点】
- 直接进行\(Q\)次基于连通性的动态规划可以获得60分。
- 注意到一定需要经过的边只有竖直的,而没有水平的。我们可以在完成一行的动态规划时顺便记录在第1行到第\(i\)行的区域中,第\(i\)行的插头为\(Mask\)的方案数以及第\(i\)行到第\(N\)行的区域中,第\(i\)行的插头为\(Mask\)的方案数。在询问时将经过某条边的配对的插头对应的方案数相乘,加入答案即可。
- 枚举配对的插头是实现中比较困难的一件事情。
- 通过适当地预处理,我们可以得到\(O(3^{M+1}*(NM+Q))\)的时间复杂度。
【代码】
#include<bits/stdc++.h> using namespace std; const int MASK = 2187; const int MAXN = 1005; const int MAXM = 15; const int P = 1e9 + 7; const int Mod = 1e6 + 3; template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } bool mp[MAXN][MAXM]; int n, m, k, q, dp[2][MASK]; bool good[MASK]; int p[MASK][MAXM]; vector <int> inv[MASK]; int bit[MAXM], num[MASK][MAXM]; int ans[MAXN][MASK], bns[MAXN][MASK]; void update(int &x, int y) {x = (x + y) % P; } void extend(int x, int y, int s, int *dest, int val) { if (mp[x][y]) { if (num[s][y - 1]) return; if (num[s][y]) return; update(dest[s], val); return; } int ts = s - bit[y - 1] * num[s][y - 1] - bit[y] * num[s][y]; if (num[s][y - 1] == 0 && num[s][y] == 0) { update(dest[ts], val); update(dest[ts + bit[y - 1] + 2 * bit[y]], val); return; } if (num[s][y - 1] == 0 && num[s][y] == 1) { update(dest[ts + bit[y - 1]], val); update(dest[ts + bit[y]], val); return; } if (num[s][y - 1] == 0 && num[s][y] == 2) { update(dest[ts + 2 * bit[y - 1]], val); update(dest[ts + 2 * bit[y]], val); return; } if (num[s][y - 1] == 1 && num[s][y] == 0) { update(dest[ts + bit[y - 1]], val); update(dest[ts + bit[y]], val); return; } if (num[s][y - 1] == 1 && num[s][y] == 1) { int tmp = p[s][y]; update(dest[ts - bit[tmp]], val); return; } if (num[s][y - 1] == 1 && num[s][y] == 2) return; if (num[s][y - 1] == 2 && num[s][y] == 0) { update(dest[ts + 2 * bit[y - 1]], val); update(dest[ts + 2 * bit[y]], val); return; } if (num[s][y - 1] == 2 && num[s][y] == 1) { update(dest[ts], val); return; } if (num[s][y - 1] == 2 && num[s][y] == 2) { int tmp = p[s][y - 1]; update(dest[ts + bit[tmp]], val); return; } } void solve(bool mode) { memset(dp, 0, sizeof(dp)); dp[0][0] = 1; int x = 1, y = 1, now = 0, dest = 1; while (x != n + 1) { if (y == m + 1) { for (int i = 0; i < MASK; i++) if (num[i][m]) break; else { dp[dest][i * 3] = dp[now][i]; if (mode) ans[x][i * 3] = dp[now][i]; else bns[x][i * 3] = dp[now][i]; } x++, y = 1; } else { for (int i = 0; i < MASK; i++) if (dp[now][i]) extend(x, y, i, dp[dest], dp[now][i]); y += 1; } memset(dp[now], 0, sizeof(dp[now])); swap(now, dest); } } int main() { read(n), read(m), read(k); for (int i = 1; i <= k; i++) { int x, y; read(x), read(y); mp[x][y] = true; } bit[0] = 1; for (int i = 1; i <= m + 1; i++) bit[i] = bit[i - 1] * 3; for (int i = 0; i < MASK; i++) { int tmp = i, pos = 0; int cnt[3] = {0, 0, 0}; while (tmp != 0) { cnt[tmp % 3]++; num[i][pos++] = tmp % 3; tmp /= 3; } if (cnt[1] != cnt[2]) continue; int stk[6], top = 2, Min = 2; memset(stk, 0, sizeof(stk)); for (int j = 0; j <= m; j++) { if (num[i][j] == 1) stk[++top] = j; if (num[i][j] == 2) { p[i][j] = stk[top]; p[i][stk[top--]] = j; } Min = min(Min, top); } if (top == 2 && Min == 2) good[i] = true; } for (int i = 0; i < MASK; i++) { if (!good[i]) continue; for (int j = 0; j < MASK; j++) { if (!good[j]) continue; int ti = i; bool flg = true; for (int k = 0; k <= m; k++) { if (num[j][k] != 1) continue; int tmp = p[j][k]; if (num[ti][k] == 0 || num[ti][tmp] == 0) { flg = false; break; } int tj = ti - num[ti][k] * bit[k] - num[ti][tmp] * bit[tmp]; if (num[ti][k] == 1 && num[ti][tmp] == 1) ti = tj - bit[p[ti][tmp]]; if (num[ti][k] == 1 && num[ti][tmp] == 2) { if (tj == 0) ti = tj; else if (p[ti][k] == tmp) { flg = false; break; } else if (p[ti][k] <= tmp && p[ti][tmp] >= k) ti = tj - bit[p[ti][k]] + bit[p[ti][tmp]]; else ti = tj; } if (num[ti][k] == 2 && num[ti][tmp] == 1) ti = tj; if (num[ti][k] == 2 && num[ti][tmp] == 2) ti = tj + bit[p[ti][k]]; } if (flg && ti == 0) inv[i].push_back(j); } } solve(true); for (int i = 1, j = n; i <= j; i++, j--) swap(mp[i], mp[j]); solve(false); read(q); while (q--) { int x, y, z; long long sum = 0; read(x), read(y), z = n - x; for (int i = 0; i < MASK; i++) if (num[i][y]) { for (unsigned j = 0; j < inv[i].size(); j++) sum += 1ll * ans[x][i] * bns[z][inv[i][j]] % P; } writeln(sum % P); } return 0; }