人間だけど競プロやる

解けなかった問題を理解できたら記事を投稿します。日本語の解説が見つからなかったもの中心。

Educational Codeforces Round 140 (Div.2) C - Count Binary Strings

まずは条件を整理する。
インデックス i,j,k があって( i \lt j \lt k ) 、

  • i から i までで条件が「2」のとき、長さ1に \{0,1\} 両方を含むことはできないので明らかに0通り。
  • i から k までの条件が「1」で j までの条件が「2」のとき j までに2種類を含むので0通り。

以上から答えが「0」のときは予め出力して処理を打ち切っておく。

上の条件を含まない時、

  • i から j の条件が「2」のときかつ k の条件が「2」のとき、k の条件は「0」と同一視してよい(\because i から j ですでに二種類ふくむ)。
  • i から k の条件が「1」のとき、すべての j の条件は「1」と同一視してよい。

よって i が始点になる条件は、「 最後の条件1のインデックス」と「最初の条件2のインデックス」だけが必要になるので変換しておく。




解法
最後に「0」になったインデックスと、最後に「1」になったインデックスを保存してDPをする。
dp[i][j][k] = i番目までみて、最後に「0」になったインデックスがj、最後に「1」になったインデックスがkとする。
遷移は次に「next = \in \{0,1\}」どちらにするかを試して、条件に違反しないなら
dp[i+1][nj][nk] += dp[i][j][k]
(nj,nkはnextの値によって最後の \{0,1\} のインデックスに更新する)

N \le 100 で条件がO(N)あるので遷移もO(N)かかかって、全体でO(10^8)

実装上ではインデックス0を「\{0,1\}」を使用していない状態とした。
よって初期化は dp[0][0][0]=1 。





条件に違反しないかの判定

(以後インデックス0は未使用状態を表すので1-indexedになっている)
例えば、j=5 ,k=8 のとき「****0111」となっている(*は \{0,1\} どちらでもよい)。

ここで x=max(j,k)+1 (xは今更新してようとしているインデックス)として、
iからx までが「条件1」とすると、

  • i \lt k のとき明らかに2種類含むので不適。
  • j \lt k なので次に採用する値next が「0」なら不適(今決めようとしている一つ前のインデックスの状態はj,kの大きい方になってるいる)。

「条件2」の判定は「条件1」の逆になる(連続しないなら2種類の数字を含む)
j,kの大小と、0(未使用)のときも含めてうまく書く。


以上を実装してAC。