Educational DP Contest DP まとめコンテスト - noko206/AtCoder GitHub Wiki

これは何?

Educational DP Contest / DP まとめコンテスト の要点や感想をまとめたページです。

問題

R - Walk

★解説AC★

行列累乗。

$dp[n][i][j]:=$ 頂点 $i$ から 頂点 $j$ へ行く長さ $n$ のパスの個数

と定義したとき、状態遷移は以下のようになる。

$dp[n][i][j]=\sum_k dp[n-1][i][k]*a[k][j]$

天才をすると、これが行列の積で書けることがわかって、 $A^K$ の各成分の合計が答えとなることがわかる。

コツとしては、↓らしい……。

  • 制約を見る
    • $N \le 50$ や、 $K$ が $10^9, 10^{18}$ みたいな場合は、サイズ $N^2$ の行列を $K$ 乗したら解けるかも
  • 繰り返しに着目
    • 同じ状態遷移を繰り返すものは行列累乗かも

https://atcoder.jp/contests/dp/submissions/49358404

↑ 行列の掛け算と累乗の計算をするライブラリを作った(パクった)。

S - Digit Sum

桁DP。

$dp[i][j][smaller]:=$ $i$ 桁目まで決定したとき、 $D$ で割った余りが $j$ で、 $smaller$ が $1$ なら $K$ 未満、 $0$ なら $K$ と等しい値の個数。

と定義する。

桁DPの要は $smaller$ なので、そこの遷移に着目すると、

  • 0 -> 0 :存在する
  • 0 -> 1 :存在しない
  • 1 -> 0 :存在する
  • 1 -> 1 :存在する

となる。

それ以外のコツとしては、↓ のような感じ。

  • 桁DPでは $K$ より大きい値となるような状態は考えない
  • 大きな桁から考えることで $smaller$ を求めやすくする
  • 初期化は $smaller$ が $1$ の状態に対して値を入れるといいかも?
  • $1$ 以上 $K$ 以下の整数を考える時、 $0$ も含めて計算して、個数をあとから引くと実装が楽になりそう

https://atcoder.jp/contests/dp/submissions/49359262

T - Permutation

★解説AC★

挿入DP。

$dp[i][j]:=$ $i$ 番目までで、最後が $j$ のときの場合の数

  • 都度 $1~i$ 番目が最後のときの場合の数を更新していく
  • その過程で累積和が必要になるのでそれで高速化する
  • 順列を考える問題は挿入DPであることを疑うのがよさそう

https://atcoder.jp/contests/dp/submissions/49562573

U - Grouping

★解説AC★ ※遷移式が思いつかなかった……。

部分集合の部分集合は $O(3^N)$ 。

$dp[S]:=$ 集合 $S$ をいくつかのグループに分けたときの総得点の最大値。

  • 集合 $S$ の部分集合 $T$ を $1$ つのグループとして、部分集合 $S/T$ と合体する遷移を考える
  • 集合 $T$ は集合 $S$ の部分集合なので、 $S/T$ は $S-T$ で計算可能
  • 部分集合をループするときは for (int T = S; ; T = (T - 1) & S) と書く
    • 終了条件や continue 条件は適宜追加する

https://atcoder.jp/contests/dp/submissions/49563903

V - Subtree

全方位木DP。

ライブラリを持っていたのでペタリ。 あとは遷移式を頑張って立てる。

  • merge(a,b):=a*b%m(部分木同士の場合の数は独立して考えられるので掛け算で求まる)
  • add_root(a):=(a+1)%m(rootを含む部分木の全ての頂点が白の場合を考慮して+1)
    • u->vに遷移するとき、頂点vが黒のときは sum_dp[u] 通り、頂点vが白のときは 1 通りであることから式を立てる
  • e():=1(add_rootで+1されて白黒両方の場合の数になるため)

get_vにrootが白の場合の数が含まれている点に注意して、 -1した値を答えとして出力する。

https://atcoder.jp/contests/dp/submissions/49585048

W - Intervals

★解説AC★

in-place DP と 遅延セグ木。

$dp[i][j]:=$ $i$ 番目まで、最後に $1$ を立てたのが $j$ 文字目のときのスコアの最大値

これだと $dp$ 配列の空間計算量に $O(N^2)$ かかってしまうので、 以下のように in-place 化する。

$dp[i]:=$ 最後に $1$ を立てたのが $i$ 文字目のときのスコアの最大値

遷移式は、

  1. $dp[i]=max(dp[j])$ $(0 \le j < i)$
  2. $dp[j]=dp[j]+a_i$ $(l \le j \le i)$

更新の順番は $i=0,1,2,...$ で、 $r=i$ となるようなスコア $a_i$ がある場合に遷移式2を行う。

文字列をすべて $0$ にするとスコアは $0$ にできるので、 スコアは $0$ 以上になる点に注意。

https://atcoder.jp/contests/dp/submissions/49608858

X - Tower

★解説AC★

一見順列を考える必要がありそうで計算量的に厳しそう。 ただ、考察を進めると最適な並び順を決定することができる。

ほぼ解説を写経した。 (解説を見るのが一番わかりやすい)

https://atcoder.jp/contests/dp/submissions/49649052

Y - Grid 2

★解説AC★

包除原理。 解説がすべて。

https://atcoder.jp/contests/dp/submissions/49687223

Z - Frog 3

★解説AC★

Convex Hull Trick。 Dynamic-Li-Chao-Treeを拝借してACした。

https://atcoder.jp/contests/dp/submissions/50233226