[AtCoder] ABC 029 D – 1
問題
方針
桁 DP を用いて考えます。\( d(i, j, k) \) を \( i \) 桁目まで調べた時、\( 1 \) の数が \( j \) であり、未満フラグが \( k \) であるものの数とします。\( k = 0 \) であるとき、\( N \) の \( i \) 桁目まで一致している状態で、\( k = 1 \) は \( N \) より小さいことが確定している状態を表します。
コード
#include <bits/stdc++.h> using namespace std; typedef long long ll; int main() { string N; cin >> N; int n = N.length(); ll d[n][n + 1][2]{}; // d[i][j][k] k: 未満フラグ, i桁目までに1がj個である数 if (N[0] == '1') { d[0][1][0] = 1; d[0][0][1] = 1; } else { d[0][0][0] = 1; d[0][1][1] = 1; d[0][0][1] = N[0] - '0' - 1; } for (int i = 0; i < n - 1; i++) { int t = N[i + 1] - '0'; // d(i, j, k) を遷移させる for (int j = 0; j < n; j++) { // d(i, j, 0) の遷移 if (t == 1) { d[i + 1][j + 1][0] += d[i][j][0]; d[i + 1][j][1] += d[i][j][0]; // i+1桁目: 0 } else { d[i + 1][j][0] += d[i][j][0]; if (t > 1) { d[i + 1][j][1] += (t - 1) * d[i][j][0]; // i+1桁目: t-1以下の1除く数字にする d[i + 1][j + 1][1] += d[i][j][0]; // i+1桁目: 1 } } // d(i, j, 1) の遷移 d[i + 1][j + 1][1] += d[i][j][1]; // i+1桁目: 1 d[i + 1][j][1] += d[i][j][1] * 9; // i+1桁目: 1以外 } } ll ans = 0; for (ll i = 1; i <= n; i++) { ans += i * (d[n - 1][i][0] + d[n - 1][i][1]); } cout << ans << "\n"; return 0; }
ディスカッション
コメント一覧
まだ、コメントがありません