h3mky0's blog

主に競プロについて書きます

AtCoder Beginner Contest 029 D - 1

問題リンク
atcoder.jp

考えたこと
1以上N以下の自然数に含まれる1の数を数え上げればよいためこれは桁dpで解くことができる.

状態の持ち方としては,
dp[i][j][k] := i番目までを見た時, (jはtightかどうか)1をk個もつような数字の個数

とする. なお, 桁数はせいぜい9なので, ある数字がもつ1の数も9が最大.

#include <bits/stdc++.h>

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    //cout << fixed << setprecision(15);
    
    string s; cin >> s;
    ll dp[15][2][10]={0};

    dp[0][0][0]=1;
    for(int i=0; i<s.size(); i++){

        int num = s[i] - '0';

        for(int j=0; j<2; j++){
            int ma = 10;

            if(j == 0){
                ma = num + 1;
            }

            for(int d=0; d<ma; d++){

                for(int k=0; k<10; k++){

                    dp[i+1][j | (d != num)][k + (d == 1)] += dp[i][j][k];
                }
            }
        }
    }
    
    int ans = 0;
    for(int i=0; i<10; i++){
        ans += (dp[s.size()][0][i]+dp[s.size()][1][i])*i;
        
    }
    cout << ans << endl;
    return 0;
}