ydc的题解是只需要两维状态 = =
可是。。。可是我必须写三维才能AC TAT
all表示区间[L, R]是(A) 还是 AB。。
为了O(1)判断处理一个二维数组的前缀和。。
还有这个鬼要特判 u == v的情况
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int read()
{
int n = 0, sign = 1; char c = getchar();
while(c < '0' || c > '9') {if(c == '-') sign = -1; c = getchar(); }
while(c >= '0' && c <= '9') { n = n*10 + c-'0'; c = getchar(); }
return n * sign;
}
const int Mod = 998244353;
const int Nmax = 305;
int N, M;
struct Square{
int sum[Nmax][Nmax];
inline void make_sum()
{
for (int i = 1; i <= N; ++i)
for (int j = 1; j <= N; ++j)
sum[i][j] += sum[i - 1][j];
for (int i = 1; i <= N; ++i)
for (int j = 1; j <= N; ++j)
sum[i][j] += sum[i][j - 1];
}
inline int get_sum(int x1, int x2, int y1, int y2)
{
int temp = sum[x2][y2] + sum[x1 - 1][y1 - 1];
temp -= sum[x1 - 1][y2] + sum[x2][y1 - 1];
return temp;
}
}s;
int dp[Nmax][Nmax][2];
inline void Add(int &a, int b)
{
a += b;
while (a > Mod) a -= Mod;
}
int dfs(int L, int R, bool all)
{
if(L == R) return all;
if(~dp[L][R][all]) return dp[L][R][all];
int &ans = dp[L][R][all] = 0;
if (all) {
if(!s.get_sum(L + 1, R, L, L)) Add(ans, dfs(L + 1, R, 0) + dfs(L + 1, R, 1));
} else for (int k = L; k < R; ++k) {
if(!s.get_sum(L + 1, k, L, L) && !s.get_sum(L, L, k + 1, R) && !s.get_sum(L + 1, k, k + 1, R))
{
//printf("%d %d %d\n", L, k, R);
Add(ans, (long long)dfs(L, k, 1) * ( (long long)dfs(k + 1, R, 0) + dfs(k + 1, R, 1) ) % Mod);
}
}
//printf("dp[%d][%d][%d] = %d\n", L, R, all, ans);
return ans;
}
int main()
{
freopen("brackets.in", "r", stdin);
freopen("brackets.out", "w", stdout);
for (int T = read(); T --; )
{
N = read(), M = read();
memset(s.sum, 0, sizeof(s.sum));
bool flag = 0;
while (M --)
{
int u = read(), v = read();
s.sum[v][u] = 1;
if (u == v) flag = 1;
}
s.make_sum();
memset(dp, -1, sizeof(dp));
printf("%d\n", flag ? 0 : (dfs(1, N, 0) + dfs(1, N, 1)) % Mod);
}
return 0;
}