目次
はじめに
この記事では、ABC380のD問題を解説していきます。
ABC(AtCoder Beginner Contest)とは、AtCoderが開催している、競技プログラミングコンテストです。
ABC380 D – Strange Mirroring
問題
英大小文字からなる文字列
- まず、
の大文字を小文字に、小文字を大文字に書き換えた文字列を とする。 - その後、
と をこの順に連結した文字列を新たな とする。
- 全ての操作を終えた後の
の先頭から 文字目を求めよ。
制約
思考の筋道
初期の文字列を
操作を繰り返すと文字列は次のようになっていきます。
操作を行うたび、
さて、
文字目は何グループ目の何番目か- そのグループは
なのか なのか
①について
各グループは当然同じ文字数なので、
なお、グループ番号も、各グループ内の番号も、0 始まりとして考えることにします。つまり、1 文字目は 0 グループ目の 0 番目と考えます。
②について
この問題の肝となる部分です。グループが
例をもとに考えてみましょう。
6グループ目はどのように作られたかをさかのぼると
2グループ目の反転によって作られたことがわかります。
(6 – 4 = 2)
0 1 2 3 | 4 5 6 7
ではその2グループ目はどのように作られたかをさかのぼると
0グループ目の反転によって作られたことがわかります。
(2 – 2 = 0)
0 1 | 2 3
0グループ目は
反転元をさかのぼることは、なるべく大きな2の累乗を引くことに対応しています。
0 になるまで 2 の累乗を引いていくことで、反転の回数が分かります。
6 – 4 = 2
2 – 2 = 0
この場合の反転回数は2回ですね。
また、上記の式は 6 = 4 + 2 とも書き表せます。この式は10進数を2進数に変形するための式です。
6 を 2進数で表すと 110 になります。このときの 1 の数が反転回数になるということです。
つまり、グループ番号を2進数に直し、1の個数の偶奇を調べれば、そのグループが
ここまで分かれば、あとは実装するのみです。
具体例で実験する中で、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問題の解説でした!
では、またね。
丁寧な解説ありがとうございます。非常に分かりやすかったです。
下記、101でなく110のタイポかと思いましてご連絡いたします。(結果には影響ないですが。)
「6 を 2進数で表すと 101 になります。」
二等兵様
本当ですね・・・。誤っていた箇所を修正しました。
ご連絡をいただき、大変助かりました。
また、分かりやすかったと言っていただき、励みになります。