题意:
\(2n\) 个人从小到大标号排成一行,有 \(m\) 对关系 \(<x,y>\)。每次可删除相邻且有关系的两人,并移动旁边的位置使队伍恢复紧凑
问把所有人删完的方案数
\(n\le 200\)
思路:
哇,一眼区间 dp + 组合数!\(f(l,r)=\sum C_{len(l,r)/2}^{len(l,k)/2}f(l,k)*f(k+1,r)\),其中 \(len(l,r)=r-l+1\)
然后重复计数,WA 了:https://atcoder.jp/contests/abc217/submissions/38271547
正解:枚举 \(l\) 与 \((l,r]\) 中的某位置 \(k\) 有联系:\(f(l,r)=\sum C_{len(l,r)/2}^{len(l,k)/2}f(l+1,k-1)*f(k+1,r)\)
const int N = 405, P = 998244353;
int n, m; bool g[N][N];
ll f[N][N], C[N][N];
ll dp(int l, int r) {
if(~f[l][r]) return f[l][r];
if(l + 1 == r) return f[l][r] = g[l][r];
if(l > r) return f[l][r] = 1;
f[l][r] = 0;
for(int k = l + 1; k <= r; k += 2)
if(g[l][k]) f[l][r] += dp(l + 1, k - 1) * dp(k + 1, r) % P
* C[(r - l + 1) / 2][(k - l + 1) / 2] % P;
return f[l][r] %= P;
}
void sol() {
cin >> n >> m; n *= 2;
while(m--) {
int x, y; cin >> x >> y;
g[x][y] = 1;
}
init(); //预处理组合数
memset(f, -1, sizeof f);
cout << dp(1, n);
}
标签:abc217,int,Make,len,Pair,return,sum
From: https://www.cnblogs.com/wushansinger/p/17065151.html