給定兩個正整數a和b,求在[a,b]中的全部整數中,每一個數碼(digit)各出現了多少次。ios
一眼識數位dp
以 \(dp[i][j]\) 對某個指定的數碼, 填了 \(i\) 位, 其中有 \(j\) 位填了特定數碼的 總數碼數
而後分一下前導零, 最高位, 數位dp便可
看代碼git
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #include<algorithm> #include<climits> #define LL long long #define REP(i, x, y) for(LL i = (x);i <= (y);i++) using namespace std; LL RD(){ LL out = 0,flag = 1;char c = getchar(); while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();} while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();} return flag * out; } const LL maxn = 19; LL num[maxn]; LL mem[maxn]; LL dp[maxn][maxn];//填完i位,填了j個給定數碼的數碼總數 LL a, b; LL DP(LL Index, LL sum, LL state, bool zero, bool limit){ if(Index == 0)return sum;//填完一組新的,總數累加sum if(!zero && !limit && dp[Index][sum] != -1)return dp[Index][sum]; LL ans = 0, up = limit ? num[Index] : 9, add = 0; REP(i, 0, up){ if(state != 0 || (state == 0 && !zero))add = (i == state); ans += DP(Index - 1, sum + add, state, zero && i == 0, limit && i == num[Index]); } if(!zero && !limit)dp[Index][sum] = ans; return ans; } LL get_num(LL x, LL state){ LL len = 0; while(x){ num[++len] = x % 10; x /= 10; } return DP(len, 0, state, 1, 1); } void init(){ a = RD(), b = RD(); memset(dp, -1, sizeof(dp)); } void solve(){ REP(i, 0, 9){ printf("%lld ", get_num(b, i) - get_num(a - 1, i)); } puts(""); } int main(){ init(); solve(); return 0; }