#define rep(l, x, a, b) for (l x = a, x##END = b; x <= x##END; ++x)
using ll = long long;
// 三种颜色分别是 1、2、3
constexpr static ll N = 1e4 + 114, Mod = 1e9 + 7;
ll me[N][N];
int T, n, m;
ll ans;
int col[N][N];
int sel[4][N]; // 由于我们搜的是列,同时还需要考虑行的情况,sel[i][x] 表示第 x 行有多少个 i 颜色
bool ok(int x, int y, int d) {
col[x][y] = d;
if(sel[1][x] <= 3 && sel[2][x] <= 3 && sel[3][x] <= 3) {
rep(int, i, 1, x - 1)
rep(int, j, 1, y - 1) { // 根据题目的约束条件检查
int d_ = col[i][j];
if((d == col[i][y] && d_ == col[x][j])
||(d == col[x][j] && d_ == col[i][y])) return 0;
}
return 1;
}
return 0;
}
void dfs(int x, int y) {
if(x > n) { // 搜完了记到 ans 里面
++ans;
return;
}
if(y > m) { // 这一列可以了,考虑下一列
dfs(++x, 1);
return;
}
rep(int, i, 1, 3) {
++sel[i][x];
if(ok(x, y, i)) // 继续搜
dfs(x, y+1);
--sel[i][x]; // 回溯掉
}
}
void solve() {
for(std::cin >> T; T--; [&](){
std::cin >> n >> m;
if(n > m) std::swap(n, m); // 优化小技巧
if(me[n][m]) return std::cout << me[n][m] << '\n', void(); // 优化小技巧
if(n == 1 || m == 1) return std::cout << 0 << '\n', void(); // 判掉只有一行或一列的情况
if(n > 9 || m > 9) return std::cout << fpow(3ll, n*m, Mod) << '\n', void();
ans = 0;
dfs(1, 1);
std::cout << (me[n][m] = (fpow(3ll, n*m, Mod) - ans + Mod) % Mod) << '\n'; // 所有情况去掉不合法情况
}());
}