【PGBattle2023】ましゅまろ 難易度5 : ダンス

[Q] https://products.sint.co.jp/hubfs/resource/topsic/pgb2023/1_4.pdf

考察
1. 区間DPで考える。
2. DP[0][N]が答え。
3. 区間の幅を2,4,6,8,…と固定し、徐々に増やして探索。
4. 固定幅の中で、FMのペアを全探索。開始地点を固定する。
5. FM区間と、その外側の区間でDPの積とcombinationの積をとる。

8のとき

FMBBBBBB // DP[0][8] += DP[1][1] * DP[2][8] * COM(4, 1)
FAAMBBBB // DP[0][8] += DP[1][3] * DP[4][8] * COM(4, 2)
FAAAAMBB // DP[0][8] += DP[1][5] * DP[6][8] * COM(4, 3)
FAAAAAAM // DP[0][8] += DP[1][7] * DP[8][8] * COM(4, 4)4通りで検証。
(Aの取り方のDP) * (Bの取り方のDP) * combination

combinationは、(FM+A)とBの取り方が独立になっているので、処理回数のCOMを求める。

実装

mint DP[101][101];
int main() {
  MOD = 998244353;
  COMinit();
  cincout();
  ll N;
  string S;
  cin >> N >> S;

  if (N % 2 == 1){
    cout << 0 << endl;
    return 0;
  }

  rep(i, N + 1) DP[i][i] = 1;
  for(ll r = 2; r <= N; r += 2){ // 幅を固定[s, s+r) DP[s][s+r]を求める
    rep(s, N - r + 1){ // 開始地点を固定
      for(ll t = s + 2; t <= s + r; t += 2){ // FMのペアを固定
        if (S[s] == S[t - 1]) continue;
        // FAAAAMBB FMが(s,t-1)で、DP[s+1][t-1]がA, DP[t][s+r]がB。 COM(all/2, (A+FM)/2)
        DP[s][s + r] += DP[s + 1][t - 1] * DP[t][s + r] * COM(r / 2, (t - s) / 2);
      }
    }
  }

  auto debug=[&](){
    rep(i, N + 1) rep(j, N + 1){
      if (DP[i][j] == 0) continue;
      cerr << "DP[" << i << "][" << j << "] = " << DP[i][j] << endl;
    }
  };
  // debug();
  cout << DP[0][N] << endl;
}

提出テストはできない。よわよわサンプルは通っているだけのコードなので、確証はない。

この記事が気に入ったらサポートをしてみませんか?