Python初心者のためのABC202
A問題
サイコロの出た面の数を とすると,反対側の面の数は と表される.
a,b,c = map(int,input().split()) # サイコロの出た面と反対側の面の数 def f(x): return 7 - x ans = f(a) + f(b) + f(c) print(ans)
以下のように簡潔に書くこともできる.
print(21 - sum(map(int,input().split())))
B問題
ポイントは以下の2つである.
- の順番が逆になる
6
は9
に,9
は6
に変換する(それ以外の文字は変わらない)
まず,文字列 の順番を逆にするためには,S = S[::-1]
とするのが最も簡単である.
これはスライスと呼ばれる操作で,文字列だけでなくリストに対しても使うことができる.
S = '0123456' # S[x]からスタートしてS[y]の手前までz文字ごとに出力する print(S[x:y:z]) # S[1]からS[6]の手前まで2文字ごとに出力する print(S[1:6:2]) > '135' # xを省略した場合は最初からスタートする # zが負の場合はSの末尾が最初として扱われる print(S[:4:1]) > '0123' # yを省略した場合は最後まで出力する # zが負の場合はSの先頭が最後として扱われる print(S[5::-2]) > '531' # x,y,zを複数省略することも可能 # 下の例だと,Sの最初から最後までを-1文字ごと=逆向きに1文字ごとに出力する print(S[::-1]) > '6543210'
次に,6
を9
に,9
を6
に変換するためには,Pythonに文字を反転させるような関数はないため,
if
文などを用いて一文字ごとに変換してやれば良い.
S = input() # 文字列を反転 S = S[::-1] ans = '' # '6'を'9'に,'9'を'6'に変換 for s in S: if s=='6': ans += '9' elif s=='9': ans += '6' else: ans += s print(ans)
文字列の変換にはS.replace(a, b)
( 内に現れる文字列 をすべて に変換する)を使っても良い.以下のように簡潔に書くこともできる.
print(input()[::-1].replace('9', '*').replace('6', '9').replace('*', '6'))
ただし,S.replace('6', '9').replace('9', '6')
のようにすると,
変換が左から順に行われるため6
が9
に変換されたあと再度6
に戻ってしまうため注意.
C問題
なる数列 を考えると, をみたす の組の個数を求める問題に帰着される. これは ABC200のC問題 と似たような感じで,各値の出現回数を管理することで解くことができる.
N = int(input()) A = list(map(int,input().split())) B = list(map(int,input().split())) C = list(map(int,input().split())) D = [B[c-1] for c in C] cntA = [0]*(N+1) for x in A: cntA[x] += 1 cntD = [0]*(N+1) for x in D: cntD[x] += 1 ans = 0 for x in range(1,N+1): ans += cntA[x] * cntD[x] print(ans)
D問題
求めたい辞書順 番目の文字列を とする.
入出力例2を見る限り全探索は無理そうなので,上手いやり方を考える必要がある.
文字列を辞書順に並べたとき,前半にa
で始まる文字列が並び,後半にb
で始まる文字列が並ぶのは簡単に予想がつく.
では,具体的に何番目までがa
から始まる文字列なのだろうか?
先頭の文字をa
で固定したとき,文字列の残りは 個のa
と 個のb
が並ぶので,
通り考えられる.
よって,辞書順で
番目から 番目までの文字列は先頭の文字が
a
番目以降の文字列は先頭の文字がb
であることが分かる. したがって, と の比較により の先頭の文字が分かる.
では,2文字目以降はどのようにして考えたら良いだろうか?
の先頭の文字がa
だった場合, の辞書順は残りの 個のa
と 個のb
が並ぶ部分で決まる.
仮にこの部分を とすると,以下の2つ
の「 個の
a
と 個のb
が並ぶ文字列」の中での辞書順
の「 個のa
と 個のb
が並ぶ文字列」の中での辞書順
は一致する.よって,
「 個の
a
と 個のb
が並ぶ文字列」の中での辞書順 番目の文字列の先頭の文字
が, の2文字目である.
の先頭の文字がb
だった場合,
先程と同様に の辞書順は残りの 個のa
と 個のb
が並ぶ部分 で決まる.
しかし, の「 個のa
と 個のb
が並ぶ文字列」の中での辞書順が 番目だとすると,
の「 個の
a
と 個のb
が並ぶ文字列」の中での 辞書順は 番目
になる.これは,「 個のa
と 個のb
が並ぶ文字列」の辞書順を考えると,
a
から始まる文字列が最初に 個並ぶためである.
この点に注意すると, の2文字目は,
「 個の
a
と 個のb
が並ぶ文字列」の中での 辞書順 番目の文字列の先頭の文字
である.
以上のように1文字目,2文字目,…と順に考えることで,辞書順で 番目の文字列の先頭の文字を求める問題に帰着される.
A,B,K = map(int,input().split()) # 二項係数 def comb(n,k): ans = 1 for i in range(k): ans *= n - i ans //= i + 1 return ans ans = '' while True: # AかBの値が0になったら残りの文字は自動的に決まる if A==0: ans += 'b'*B break if B==0: ans += 'a'*A break # 先頭の文字はどっち? if K <= comb(A+B-1, A-1): ans += 'a' A -= 1 else: ans += 'b' K -= comb(A+B-1, A-1) B -= 1 print(ans)