おじさんの競プロ記録

自分の力で解答できた問題を振り返り、理解を深めたいです。

SOMPO HD プログラミングコンテスト2021(AtCoder Beginner Contest 192) C - Kaprekar Number

問題

問題文へ 0以上の整数xに対して、 g_1(x),g_2(x),f(x)を次のように定めます。

  •  g_1(x) = xを10進法で表したときの各桁の数字を大きい順に並び替えてできる整数
  •  g_2(x) = xを10進法で表したときの各桁の数字を小さい順に並び替えてできる整数
  •  f(x) = g_1(x) - g_2(x)

整数N,Kが与えられるので、 a_0 = N, a_{i+1} = f(a_i)(i \leq 0)で定まる数列の a_kを求めてください。

制約

  •  0 \leq N \leq 10^9
  •  0 \leq K \leq 10^5
  • 入力はすべて整数

考えたこと

各関数を実装します。Kが最大で 10^5なので、 a_kまでシミュレートしても間に合います。

コード

#define _GIBCXX_DEBUG
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define all(v) v.begin(), v.end()
using namespace std;
using ll = long long;

int g1(int a) {
    vector<int> v;
    while (a > 0) {
        v.push_back(a % 10);
        a /= 10;
    }
    sort(v.begin(), v.end(), greater<int>());

    int res = 0;
    for (auto i : v) {
        res *= 10;
        res += i;
    }
    return res;
}

int g2(int a) {
    vector<int> v;
    while (a > 0) {
        v.push_back(a % 10);
        a /= 10;
    }
    sort(v.begin(), v.end());

    int res = 0;
    for (auto i : v) {
        if (i == 0) continue;
        res *= 10;
        res += i;
    }
    return res;
}

int f(int a) {
    return g1(a) - g2(a);
}

int main(void) {
    int N, K;
    cin >> N >> K;

    int ans;
    for (int i = 0; i <= K; ++i) {
        if (i == 0) {
            ans = N;
            continue;
        }

        ans = f(ans);
    }

    cout << ans << endl;
    
    return 0;
}

解説を読んで

stringを使うことで実装が楽になる。それ以前に関数で切り出すべきでしたね。