ABC 154

https://atcoder.jp/contests/abc154

A. Remaining Balls

https://atcoder.jp/contests/abc154/tasks/abc154_a

B. I miss you

https://atcoder.jp/contests/abc154/tasks/abc154_b

C. Distinct or Not

https://atcoder.jp/contests/abc154/tasks/abc154_c

D. Dice in Line

https://atcoder.jp/contests/abc154/tasks/abc154_d

E. Almost Everywhere Zero

https://atcoder.jp/contests/abc154/tasks/abc154_e

自力 AC. 桁 DP の問題だということをわかった上で解いた。

dp[i][is_less][c] を上位 $i$ 桁目まで見ていて、$N$ よりも小さいことが確定しているフラグ is_less と、0 以外の数字の個数 c を持つ DP 配列を定義する。 dp 配列を更新する際、$0$ 以外の数が $K+1$ となるケースは興味ないので全て $K+1$ に丸めておく。

void solve() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    string N;
    ll K;
    cin >> N >> K;

    int M = N.size();
    vector dp(M + 1, vector(2, vll(K + 2)));
    dp[0][0][0] = 1;
    rep2(i, 1, M + 1) {
        int t = N[i - 1] - '0';
        rep(d, 10) {
            int is_not_zero = d != 0;
            rep(c, 4) {
                int nxc = min(c + is_not_zero, K + 1);
                if (d < t) {
                    dp[i][1][nxc] += dp[i - 1][0][c];
                }
                if (d == t) {
                    dp[i][0][nxc] += dp[i - 1][0][c];
                }
                dp[i][1][nxc] += dp[i - 1][1][c];
            }
        }
    }

    ll ans = dp[M][1][K] + dp[M][0][K];
    cout << ans << endl;
}

F. Many Many Paths

https://atcoder.jp/contests/abc154/tasks/abc154_f