標籤:
How Many O‘s?
題意是求區間內數字中0的個數,比如100就有兩個0。
數位dp吧,dp[i][j][k], i很明顯表示當前位置,j表示找到的0的個數,k表示要找的0的個數。因為數字裡0的個數最多32個,所以可以枚舉32種k的情況,用數位dp去找。
#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>using namespace std;#define ll long longint dig[20];ll dp[40][40][40];int bigcnt;ll dfs(int pos, int cnt, int flag, int lim) { if(pos == -1) return cnt == 0; if(cnt < 0) return 0; if(!flag && !lim && dp[pos][cnt][bigcnt] != -1) return dp[pos][cnt][bigcnt]; int End = lim ? dig[pos] : 9; ll ret = 0; for(int i = 0; i <= End; i++) { if(flag && !i) ret += dfs(pos - 1, bigcnt, 1, lim && (i == End)); else if(flag && i) ret += dfs(pos - 1, bigcnt, 0, lim && (i == End)); else if(!flag && i) ret += dfs(pos - 1, cnt, 0, lim && (i == End)); else if(!flag && !i) ret += dfs(pos - 1, cnt - 1, 0, lim && (i == End)); } if(!lim && !flag) dp[pos][cnt][bigcnt] = ret; return ret;}ll func(ll num) { ll ret = 0; if(num == -1) return -1; int n = 0; while(num) { dig[n++] = num % 10; num /= 10; } for(int i = 1; i <= 32; i++) { bigcnt = i; ret += i * dfs(n - 1, i, 1, 1); } return ret;}int main() { ll a, b; memset(dp, -1, sizeof(dp)); while(~scanf("%lld %lld", &a, &b)) { if(a < 0) break; printf("%lld\n", func(b) - func(a - 1)); }}
UVA - 11038 How Many O's? (數位dp)