abc217 F - Make Pair

题意:

\(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);
}
posted @ 2023-01-23 14:13  Bellala  阅读(39)  评论(0)    收藏  举报