Official

C - Repunit Trio Editorial by nok0


evima さんの別解 のほうが単純なので、そちらもお読みください。

ちょうど \(3\) つのレピュニットの和として表せるという条件を言い換えると以下になります。

  • 各桁は \(1\) 以上 \(3\) 以下の整数であり、上から下で単調増加になっている
  • 最も下の桁(1 の位)は \(3\) である

つまり、条件を満たす数は \(1\)\(0\) 個以上、\(2\)\(0\) 個以上、\(3\)\(1\) 個以上並んでいると表すことができます。

この言いかえを用いると全探索ができます。 \(1\) の個数、\(2\) の個数、\(3\) の個数を適当な範囲で全探索すればよいです。本問題で与えられる \(N\) の制約では、候補の数として \(12\) 桁まで調べれば十分です。(これは、サンプルを見る/適当に探索する/数式で評価する 等の方法で確認できます。)

全探索の順番を工夫することで、\(\mathrm{O}(N)\) で解くこともできますが、本制約では候補を列挙して昇順に並び替えて \(N\) 番目を求める \(\mathrm{O}(N\log N)\) 解法でも十分高速です。

実装例(C++):

#include <bits/stdc++.h>
using namespace std;
int main() {
  int n;
  cin >> n;
  for(int d = 1; d <= 12; d++) {
    for(int a = d - 1; a >= 0; a--) {
      for(int b = d - a - 1; b >= 0; b--) {
        int c = d - a - b;
        if(--n == 0) {
          cout << string(a, '1') + string(b, '2') + string(c, '3') << endl;
          return 0;
        }
      }
    }
  }
}

posted:
last update: