くすと日記

競技プログラミングとか

AtCoder Regular Contest 138 振り返り

AtCoder Regular Contest 138に参加しました。

結果

f:id:kusto:20220410023000p:plainf:id:kusto:20220410022934p:plain

B問題のみAC。緑まであと少し!

 B - 01 Generation

問題概要

空の数列xに対して以下の操作を任意の順番で行い、指定された数列を作れるか?

  • 操作A:xの要素すべてをflip(1なら0、0なら1に)した後、先頭に0をつける
  • 操作B:xの末尾に0をつける

作れるかどうかをYes/Noで回答する。

考察

空の数列に対してA/Bどちらの操作を行っても[0]になるので、[0]から始めると考えます。

操作Aのみ行った場合、数列は次のように変化していきます。

0 → 01 → 010 → 0101 → 01010 → 010101

次に操作A/B両方行った場合を考えます。

操作Bは最初の0よりも右側にしか影響しないので、最初の0より左側は、操作Aのみ行った場合と同様、先頭が0で、以降1/0が交互に並びます。

 

具体例として数列 0100110 で考えていきます。

前述のとおり、左端から0/1が交互に並んでいる部分は操作Aで作ることができます。

この例では、左から3個、010の部分が操作Aで作れます。数列[0]から始めると考えると、2回の操作A010を作れます。操作Aが3回以上行われた場合は010...がより長く続くはずなので、操作Aは2回までしか行われていません。

 

次に、残りの0110の部分を操作A/Bで作れるかどうか考えます。

  • 各数字は、その位置に0が追加されて以降にflipされた回数(=操作Aの回数)の偶奇を意味しています。
  • 数字は左から右に向かって追加されていくので、各数字のflip回数は右隣の数字のflip回数より多いか同じになります。

以上の条件を満たすように各数字のflip回数を決定し、最低限必要なflip回数が操作Aの回数(2回)以下であれば、数列0100110を作ることができます。

 

右端の数字は、数字が0ならflip回数0、1なら1です。

右端から左へ辿っていくと、数字(0/1)が変化する部分でflip回数が1増えることになります。

f:id:kusto:20220410022051p:plain

この例では、0110の部分を作るのに最低限2回のflip(操作A)が必要ということがわかります。

010の部分は2回のA操作で作れるので、0100110は操作A/Bで作ることができます。