✨
ABC202 D aab aba baa[python]
URL
制約
K はありうる総数以下
問題概要
- A個のa とB個のb からなる長さA+Bの文字列のうち、辞書順でK番目のものを求めよ
提出コード
a, b, k = map(int, input().split())
ans = ""
def comb(a, b):
"""return combination aCb
Args:
a ([int]]):
b ([type]):
Computation Complexity:
O(b)
"""
numerator = 1
denomirator = 1
for i in range(b):
numerator *= a-i
denomirator *= b-i
return numerator//denomirator
exist_a = a
exist_b = b
for i in range(a+b):
if exist_a == 0:
ans += "b"*exist_b
break
if exist_b == 0:
ans += "a"*exist_a
break
if k <= comb(exist_a+exist_b-1, exist_a-1):
ans += "a"
exist_a -= 1
else:
k -= comb(exist_a+exist_b-1, exist_a-1)
ans += "b"
exist_b -= 1
print(ans)
考察
- 辞書順で何番目か?はよくある問題。桁dp とかで解く印象
- 最初の文字から順番に決めることができる
- 現在 i 文字目まで決まっているとして、残りのA+B-i 文字の中でa がx 、bがy 残っているとすると、次にa がくるのは、
であるときで、それ以外のケースではbを使う。
bを使う場合は
をkから引いて行けば良い
実装方針
- 先頭の文字から順番でa or b を決める(for)
- if
なら a にしてそのまま、それ以外ならその数を引いてb にする を 最後の文字まで続けるk <= {x+y-1 \choose x-1}
次回への反省
- 最初の実装では片方の文字がなくなっても実装方針で書いたループを継続していたので存在しない文字列(全部a とか)を生成していた(以下最初に書いたWAコード)
WA.py
a, b, k = map(int, input().split())
ans = ""
def comb(a, b):
"""return combination aCb
Args:
a ([int]]):
b ([type]):
Computation Complexity:
O(b)
"""
numerator = 1
denomirator = 1
for i in range(b):
numerator *= a-i
denomirator *= b-i
return numerator//denomirator
exist_a = a
exist_b = b
for i in range(a+b):
if i == a+b-1: # 最後だけは例外処理
if exist_a:
ans += "a"
else:
ans += "b"
break
if k <= comb(exist_a+exist_b-1, exist_a-1):
ans += "a"
exist_a -= 1
else:
k -= comb(exist_a+exist_b-1, exist_a-1)
ans += "b"
exist_b -= 1
print(ans)
- 小さいテストケースでどうなるかサンプルとは別に試す
- ある値が0になるときや負になるようなケースは特に注意してそのままでいいか検討する
Discussion