ゆるふわ競プロ

Javaでゆるゆる競プロしています.忘れっぽいのでメモ用,復習用

ABC099<難問>

問題

AtCoder
ある数字Nが与えられる。
1,6,36(62),216(63)....,9,81(92),729(93)....
の総和で表すとき、項数をもっとも少なくする。項数を求めよ。

考察

N以下で最大の数を無理やり持って来ればいいのではないか。全探査のようにN以下で最大の6の累乗と9の累乗を取って来て比較して大きい方を採用する。これを繰り返せば行けそう。

public static int SelectMaxNumber(int n) {
        int sixMax = 0;
        int nineMax = 0;
        for (int i = 1; Math.pow(6, i) <= n; i++) {
            sixMax = (int) Math.pow(6, i);
        }
        for (int i = 1; Math.pow(9, i) <= n; i++) {
            nineMax = (int) Math.pow(9, i);
        }
        return sixMax <= nineMax ? nineMax : sixMax;
    }

なんども使いそうだったので新しく関数を作る。

        int count = 0;
        while (n >= 6) {
            int a = SelectMaxNumber(n);
            n = n - a;
            count++;
        }

これでcountに項数(和の回数)が蓄積されていき最後にn(1を何回か足す)ことで項数が求まる。

結果 -> 失敗

原因 n = 108 の場合
上記のやり方
108 = 81 + 9 + 9 + 9;
最小にするには
108 = 36 + 36 + 36;
手計算だと理解できるが、プログラムで書くとなると難しい。
やり方自体が間違っていそう.

別案

6a = 3a × 2a
9b = 3b × 3b
を用いることはできないだろうか。
共に3の倍数であるので3くくってみるとする。
N = 3 × ( ) + α
α 偶奇で場合分けする(頭をよぎった)6の累乗は常に偶数9の累乗は常に奇数である。
これが何かに使えるかと行かれたら微妙である。9の累乗の和は偶数になることができてしまう。