看题解解的。将着色方案映射为40*40*5*5*5*5*2个状态,40*40表示n*m,5*5*5*5表示上下左右相邻块的颜色,0表示未着色。
2表示横切或者竖切。
基本思路是记忆化搜索然后去重,关键点是可能未切前当前块已经着色了。
/* 4363 */
#include <iostream>
#include <sstream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000") #define sti set<int>
#define stpii set<pair<int, int> >
#define mpii map<int,int>
#define vi vector<int>
#define pii pair<int,int>
#define vpii vector<pair<int,int> >
#define rep(i, a, n) for (int i=a;i<n;++i)
#define per(i, a, n) for (int i=n-1;i>=a;--i)
#define clr clear
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1 const int mod = 1e9+;
int dp[][][][][][][]; int calc(int x, int y, int u, int d, int l, int r, int dir) {
if (dp[x][y][u][d][l][r][dir] >= )
return dp[x][y][u][d][l][r][dir]; int& ret = dp[x][y][u][d][l][r][dir]; ret = ;
if ((x==&&dir==) || (y==&&dir==)) {
rep(i, , )
if (i!=u && i!=d && i!=l && i!=r)
++ret;
return ret;
} if (dir) {
rep(i, , y) {
rep(j, , ) {
if (j!=u && j!=d && j!=l) {
ret = (ret + calc(x, y-i, u, d, j, r, )) % mod;
}
if (j!=u && j!=d && j!=r) {
ret = (ret + calc(x, i, u, d, l, j, )) % mod;
}
}
} int tmp = ;
rep(i, , ) {
if (i!=u && i!=d && i!=l) {
rep(j, , ) {
if (j!=u && j!=d && j!=r && j!=i)
++tmp;
}
}
} ret = (ret + mod - tmp*(y-)) % mod;
rep(i, , )
if (i!=u && i!=l && i!=r && i!=d)
++ret; ret %= mod;
} else {
rep(i, , x) {
rep(j, , ) {
if (j!=u && j!=l && j!=r) {
ret = (ret + calc(x-i, y, j, d, l, r, )) % mod;
}
if (j!=d && j!=l && j!=r) {
ret = (ret + calc(i, y, u, j, l, r, )) % mod;
}
}
} int tmp = ;
rep(i, , ) {
if (i!=u && i!=l && i!=r) {
rep(j, , ) {
if (j!=d && j!=l && j!=r && j!=i)
++tmp;
}
}
} ret = (ret + mod - tmp*(x-)) % mod;
rep(i, , )
if (i!=u && i!=l && i!=r && i!=d)
++ret; ret %= mod;
} return ret;
} int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif int t;
int n, m;
int ans; memset(dp, -, sizeof(dp));
scanf("%d", &t);
while (t--) {
scanf("%d %d", &n, &m);
ans = calc(n, m, , , , , );
printf("%d\n", ans);
} #ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif return ;
}