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

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

AtCoder AGC 021 A - Digit Sum 2 (灰色, 300 点)

少し慎重に

問題概要

 N 以下の正の整数の 10 進法での各桁の和の最大値を求めよ。

制約

  •  1 \le N \le 10^{16}

考えたこと

 N = 35312 とかだったら答えは  29999 になりそうだ。一般に、

 a99999

の形をしたものだけ考えれば良さそう。仮に  a99899 とかが最適解だったとしても、その場合は  b = a-1 として、 b99999 (\lt a99899) も最適解になるのだ。このような議論を深めれば、" a99999" の形のみ考えれば良いことがわかる。

具体的には、 N の桁数を  d、最上位の桁の値を  a としたとき、 b = a-1 として次のようになる。

  •  N = a99...9 ( 9 d-1 個) ならば、これが答え
  •  N \lt a99...9 ( 9 d-1 個) ならば、 b99...9 が答え
    •  a = 1, b = 0 であっても、問題ない

計算量は  O(\log N)

コード

実装上は、あらかじめ  N に 1 を足しておくといい感じ。そうすると統一的に

  •  N の最上位の桁の値を 1 減らす (0 になってもよい)
  • それ以外の桁の値を 9 にする

としたものが答えとなる。

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

int main() {
    long long N;
    cin >> N;
    ++N;
    long long res = 0;
    while (N) {
        if (N < 10) res += N-1;
        else res += 9;
        N /= 10;
    }
    cout << res << endl;
}