AtCoder Beginner Contest 099 C – Strange Bank をPython3で解く

Share

AtCoder上にある問題のうち、AtCoder Problemsでdiff 800以上と判定されているものを順番に解いていく企画。
基本的な考え方は全てコード中のコメントに入れてあるので、参照のこと。

出典:
AtCoder Beginner Contest 099 C – Strange Bank

どんな銀行やねん……と突っ込まざるを得ない問題。

# AtCoder Beginner Contest 099 C - Strange Bank
# https://atcoder.jp/contests/abc099/tasks/abc099_c
# tag: N進数

# 6 進数と 9 進数の組み合わせを考える問題。
# 幸い 1 <= N <= 100000 と制約が緩いので、
# 6 進数で数える分と 9 進数で数える分をわけることにして、全探索する。

def main():
    N = int(input())

    # ある数 x を p 進法で考えたときの
    # 各桁の数字の合計を返す関数を作成しておく。
    def get_op_num(x, p):
        result = 0
        while x:
            result += x % p
            x //= p
        return result

    result = N
    # 9 進法で数える分を 0 ~ N の範囲で動かし、全探索を行う。
    # 1 円の桁はどちらで数えても同じなので、9 の倍数だけ調べていく。
    for p_nine in range(0, N+1, 9):
        tmp = get_op_num(p_nine, 9) + get_op_num(N - p_nine, 6)
        if result > tmp:
            result = tmp
    
    print(result)

main()

ついでにメモ化再帰でも解いてみた。

# メモ化再帰を用いた場合
import sys
sys.setrecursionlimit(10**9)
def main():
    N = int(input())

    # dpt[x]: x 円を引き出すために必要な最小回数
    dpt = [-1] * (N+1)
    dpt[0] = 0

    def get_min_op(x):
        # メモがあればそれを返す。
        if dpt[x] != -1:
            return dpt[x]
        
        # 最大は x 回
        result = x

        # 1 円を引き出す場合
        tmp_r = get_min_op(x - 1) + 1
        if result > tmp_r:
            result = tmp_r

        # 9^n 円を引き出す場合
        prev = 9
        while prev <= x:
            tmp_r = get_min_op(x - prev) + 1
            if result > tmp_r:
                result = tmp_r
            prev *= 9

        # 6^n 円を引き出す場合
        prev = 6
        while prev <= x:
            tmp_r = get_min_op(x - prev) + 1
            if result > tmp_r:
                result = tmp_r
            prev *= 6
        
        dpt[x] = result
        return result

    result = get_min_op(N)
    print(result)
main()
Share

コメントを残す

メールアドレスが公開されることはありません。