ebisukeプログラミング初心者脱出黙示録

30歳を過ぎてから始めたプログラミングと競プロの記録。Pythonで取り組んでいます。Arduinoで電子工作も

SOMPO HD コンテスト(ABC192 D - Base n)【Python解答例】

SOMPO HD プログラミングコンテスト(ABC192)で解けなかったD問題を復習していきます。
atcoder.jp



AtCoder Beginner Contest192 D - Base n

D - Base n

問題文

0 ~ 9 からなる文字列 X と、整数 M が与えられます。
X に含まれる最も大きい数字を d とします。
d+1 以上の整数 n を選んで X を n 進法表記の数とみなして得られる値のうち、M 以下であるようなものは何種類あるでしょうか?

制約

・X は 0 ~ 9 のみからなる
・X の長さは 1 以上 60 以下
・X の先頭の文字は 0 ではない
・1≤M≤10^18

解答例

x = input()
m = int(input())

def Base_n_to_10(X,N): # N進数のXを10進数に変換
    out = 0
    for i in range(1,len(str(X))+1):
        out += int(X[-i])*(N**(i-1))
    return out

d = 0
for i in range(len(x)): # dを求める
    d = max(d,int(x[i]))

n = d

if len(x) == 1:  # Xが一桁の場合はコーナーケース
    if int(x) <= m:
        ans = 1
    else:
        ans = 0
else: # 二分探索
    left = n
    right = m + 1
    while right - left > 1:
        mid = (left + right) // 2
        if Base_n_to_10(x,mid) > m:
            right = mid
        else:
            left = mid
    ans = left - n
print(ans)

解説

まずX に含まれる最も大きい数字dを求め、二分探索で答えを求めていきました。

Xが1桁のときはコーナーケースになります。
例えばX =2とするとn = 3なので3進数の2は2のままです。
n = 4にしても4進数の2は2のままなので値は同じになります。
問題文から値の数を答えなければならないので、XがMより小さければ答えは1、大きければ答えは0となります。

Xが2桁以上のときは二分探索をおこないます。
dからm+1の範囲で探索します。
N進数のXを10進数に変換するのはBase_n_to_10関数で行いました。

探索が終わったら求める答えはleft - nとなりますので、それを出力すればACでした。



二分探索の実装がむずかしかったです…
練習がたりませんね (^_^;)


ABC192の関連記事はこちら
ebisuke33.hatenablog.com
ebisuke33.hatenablog.com