BZOJ 1833 count 數字計數 (數位DP)
阿新 • • 發佈:2018-10-31
任重而道遠
給定兩個正整數a和b,求在[a,b]中的所有整數中,每個數碼(digit)各出現了多少次。
Input
輸入檔案中僅包含一行兩個整數a、b,含義如上所述。
Output
輸出檔案中包含一行10個整數,分別表示0-9在[a,b]中出現了多少次。
Sample Input
1 99
Sample Output
9 20 20 20 20 20 20 20 20 20
Hint
30%的資料中,a<=b<=10^6;
100%的資料中,a<=b<=10^12。
AC程式碼:
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> using namespace std; #define ll long long ll digit[15], dp[15][2][15][2]; ll a, b, cnt; ll dfs (int dep, int sj, int x, ll sum, int zero) { if (!dep) return sum; if (dp[dep][sj][sum][zero]) return dp[dep][sj][sum][zero]; int i = sj ? digit[dep] : 9; ll tmp = 0; for (int k = i; k >= 0; k--) { if ((k == x) && (k || !zero)) tmp += dfs (dep - 1, sj && (k == digit[dep]), x, sum + 1, zero && (k == 0)); else tmp += dfs (dep - 1, sj && (k == digit[dep]), x, sum, zero && (k == 0)); } dp[dep][sj][sum][zero] = tmp; return tmp; } ll solve (ll x, int i) { memset (dp, 0, sizeof (dp)); memset (digit, 0, sizeof (digit)); cnt = 0; while (x) { digit[++cnt] = x % 10; x /= 10; } return dfs (cnt, 1, i, 0, 1); } int main () { cin >> a >> b; for (int i = 0; i <= 9; i++) { cout << solve (b, i) - solve (a - 1, i) << " "; } return 0; }