geam1113’s diary

主にAtcoderのコンテストの備忘録を書きます。AtCoder緑と水色を行ったり来たりしています。

ABC242D ABC Transform

解説AC

問題へのリンク
公式解説へのリンク

テキストとyoutubeの解説の自分用まとめです。特に新しいことはありません。公式を見た方が詳細です。

二分木として考える

各文字が2つの文字になることを順に図示すると、二分木の構成になります。

よって、この問題は、

S^{(0)}_0,\ S^{(0)}_1,\ \cdots S^{(0)}_{N-1}を根とする二分木における、深さtk番目の文字を求めよ

という問題と見ることができます。

mod\ 3における0,1,2をA,B,Cに対応させます。
Aの左子ノードがB、右子ノードがCであるとします。
左子ノードに進むことは、mod\ 3において+1すること、右子ノードに降りることは+2することと同じです。B,Cにおいても同様に考えることができます。

よって、親の文字がわかれば子の文字を求めることができます。

以降、+xするという表現はmod\ 3上での操作を指します。

親と子の番号の関係

深さtにおいて、k番目である場合、その子は、深さt+1において、左子ノードが2k番目、右子ノードが2k+1となります。

以下が理由です。
深さtにおいてk番目である場合、自分より前には0,...,k-1までのk個のノードが存在する。
深さt+1には、それらの子ノードが2個ずつ存在し、その数は2k個となる。それらの番号は、0,...,2k-1となるから。

これより、

  • 親がk番目なら、子の番号は左が2k、右が2k+1
  • 子の番号がkなら親の番号は、\lfloor \frac{k}{2} \rfloor

が言えます。
また、

  • 子の番号が偶数なら親の左子ノード、奇数なら右子ノード

も言えます。

tが小さい場合

解説にならって、S^{(t)}k番目の文字を求める関数をf(t,k)とおきます。

以下のように再帰的に求められます。

f(t-1,\lfloor \frac{k}{2} \rfloor )を求め、kが偶数なら+1、奇数なら+2します。
tが十分小さい場合、再帰の過程でt=0となります。この時、f(0,k')S^{(0)}_{k'}として返せばよいです。

tが大きい場合

深さが1増えると子の数は2倍になります。
深さdから、60回深いところに進むと、0,...,2_{60}-1番目の文字は全てS^{(d)}_0の子孫であることがわかります。

kの最大値は10^{18} \lt 2^{60}-1であることから、tから60回ほど親を遡ったところをt'とすれば、深さtk番目の文字は全てS^{(t')_0}の子孫となります。

ある深さdにおけるS^{(d)}_0は、全てS^{(0)}_0の左子ノードをd回進んだ文字であるので、S^{(0)}_0+dすることで求められます。

以上より、再帰においてkを1/2していくと、高々60回ほどで、k=0となります。このとき、f(t',0)S^{(0)}_0+t'として返すようにすればよいです。
提出コード(公式とほぼ同じ)