ABC380 D問題の解説(Python)

はじめに

この記事では、ABC380のD問題を解説していきます。

ABC(AtCoder Beginner Contest)とは、AtCoderが開催している、競技プログラミングコンテストです。

ABC380 D – Strange Mirroring

問題

問題

英大小文字からなる文字列 S が与えられます。

S に以下の操作を 10100 回繰り返します。

  • まず、 S の大文字を小文字に、小文字を大文字に書き換えた文字列を T とする。
  • その後、 S と T をこの順に連結した文字列を新たな S とする。

Q 個の質問に答えて下さい。 そのうち i 個目は次の通りです。

  • 全ての操作を終えた後の S の先頭から Ki​ 文字目を求めよ。

制約

  • 1len(S)2×105
  • 1Q2×105
  • 1Ki1018

思考の筋道

初期の文字列を S0、初期の文字列の大文字と小文字を反転した文字列を T0 と表すことにします。

操作を繰り返すと文字列は次のようになっていきます。

  • S0
  • S0 T0
  • S0 T0 T0 S0
  • S0 T0 T0 S0 T0 S0 S0 T0

操作を行うたび、S0T0 のグループの数が倍に増えていることがわかります。

さて、S の先頭から Ki​ 文字目が何であるかを知るには、次のことが分からなければなりません。

  1. Ki​ 文字目は何グループ目の何番目か
  2. そのグループは S0 なのか T0 なのか
①について

各グループは当然同じ文字数なので、Ki をその文字数で割った商と余りを調べることで、Ki​ 文字目が何グループ目の何番目か分かります。

なお、グループ番号も、各グループ内の番号も、0 始まりとして考えることにします。つまり、1 文字目は 0 グループ目の 0 番目と考えます。

②について

この問題の肝となる部分です。グループが S0 なのか T0 なのかをどのように調べればよいでしょうか?

例をもとに考えてみましょう。

6グループ目は S0T0

6グループ目はどのように作られたかをさかのぼると
2グループ目の反転によって作られたことがわかります。
(6 – 4 = 2)
0 1 2 3 | 4 5 6 7

ではその2グループ目はどのように作られたかをさかのぼると
0グループ目の反転によって作られたことがわかります。
(2 – 2 = 0)
0 1 | 2 3

0グループ目は S0 であり、6グループ目に至るまでに2回反転していることから、6グループ目は S0 と分かります。

反転元をさかのぼることは、なるべく大きな2の累乗を引くことに対応しています。

0 になるまで 2 の累乗を引いていくことで、反転の回数が分かります。
6 – 4 = 2
2 – 2 = 0
この場合の反転回数は2回ですね。

また、上記の式は 6 = 4 + 2 とも書き表せます。この式は10進数を2進数に変形するための式です。

6 を 2進数で表すと 110 になります。このときの 1 の数が反転回数になるということです。

つまり、グループ番号を2進数に直し、1の個数の偶奇を調べれば、そのグループが S0T0 か分かるということですね。

ここまで分かれば、あとは実装するのみです。

具体例で実験する中で、2進数の背景に気づけるかどうかがポイントでした。

コード

S = input()
Q = int(input())
K = list(map(int, input().split()))

ans = []

for num in K:
    q = (num - 1) // len(S)
    r = (num - 1) % len(S)
    bin_q = bin(q)[2:]
    mirror_count = bin_q.count("1")
    if mirror_count % 2 == 0:
        ans.append(S[r])
    else:
        ans.append(S[r].swapcase())

print(*ans)

以上、ABC380のD問題の解説でした!

では、またね。

リンク

    2件のコメント

    丁寧な解説ありがとうございます。非常に分かりやすかったです。
    下記、101でなく110のタイポかと思いましてご連絡いたします。(結果には影響ないですが。)

    「6 を 2進数で表すと 101 になります。」

    二等兵様
    本当ですね・・・。誤っていた箇所を修正しました。
    ご連絡をいただき、大変助かりました。
    また、分かりやすかったと言っていただき、励みになります。

    コメントを書く