けんちょんの競プロ精進記録

競プロの精進記録や小ネタを書いていきます

AtCoder ABC 372 B - 3^A (5Q, 灰色, 200 点)

三進法をテーマにした問題!

問題概要

正の整数  M が与えられる。以下の条件を全て満たす正の整数  N と非負整数列  A_{1}, A_{2}, \dots, A_{N} を 1 つ求めよ。

  •  1 \le N \le 20
  •  0 \le A_{i} \le 10
  •  \displaystyle \sum_{i = 1}^{N} 3^{A_{i}} = M

制約

  •  1 \le M \le 10^{5}

考えたこと

問題文が一見わかりにくいかもしれない。こういうときは具体的にやってみよう。

たとえば  M = 47 のとき、47 を三進法で表すと、1202 となる。このことは、

 47 = 3^{3} + 2 \times 3^{2} + 2 \times 3^{0}
 = 3^{3} + 3^{2} + 3^{2} + 3^{0} + 3^{0}

と表せることを意味する。

一般に、整数  M を考える。 M を三進法で表したとき、 3^{i} の位の値の個数に応じて  3^{i} を足していけばよいことがわかる。

 M を三進法で表すためには、


  •  M を 3 で割った余りを求める
  •  M を 3 で割った商で置き換える

という操作を繰り返していけば良い。

コード

#include <bits/stdc++.h>
using namespace std;

int main() {
    int M, offset = 0;
    cin >> M;
    vector<int> res;
    while (M) {
        for (int i = 0; i < M % 3; i++) res.push_back(offset);
        M /= 3;
        offset++;
    }
    cout << res.size() << endl;
    for (int i = 0; i < res.size(); i++) cout << res[i] << " ";
    cout << endl;
}