HDU 3555 數位DP 入門
阿新 • • 發佈:2019-02-01
/** * 數位dp: * 和hdu 2089 類似,不過這個其實更簡單。 * 不過有一點不同的是,在計數的時候,因為要找的是子串“49”, * 所以不需要考慮在if(num[i] > 9 && last == 4) 的情況 * 而hdu 2089的子串是“62”,也就是當在if(num[i] > 2 && last == 6)情況的時候 * 仍需考慮num[i] > 2,因為這裡還有個num[i]取2的數,所以要多加個 dp[i][1]; * 其次就是num[i] == 9的時候,這個一開始想了有點久,為什麼num[i]=9, num[i+1]=4 * 的時候不需要算呢? 也就是為什麼是if(num[i] > 9 && last == 6) 而不是 if(num[i] >= 9 && last == 6) * 其實當num[i] = 9, num[i+1] = 4 的時候把flag設成true,也就是表示已經出現了以49xxx形式的數 * 其實這裡就已經算了49xxx了,就不用在當前步算49,而是在之後的flag為true的時候都是這種情況。 */ #include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <string> #include <queue> #include <map> #include <vector> #include <algorithm> #define DEBUG 0 #define INF 0x1fffffff #define MAXN 25 typedef long long LL; using namespace std; int num[MAXN]; LL dp[MAXN][3]; // 0-所有不存在 1-不存在以9開頭 2-存在 LL cal(LL x) { int cnt = 1; while(x) { num[cnt++] = x % 10; x /= 10; } int last = 0, flag = 0; LL ans = 0; for(int i = cnt - 1; i > 0; i --) { ans += dp[i-1][2] * num[i]; // 0 - 4 if(flag) { ans += dp[i-1][0] * num[i]; } else { if(num[i] > 4) { ans += dp[i-1][1]; } } if(last == 4 && num[i] == 9) flag = 1; last = num[i]; } return ans; } int main() { int t; memset(dp, 0, sizeof(dp)); dp[0][0] = 1; for(int i = 1; i < 20; i ++) { dp[i][0] = dp[i-1][0] * 10 - dp[i-1][1]; dp[i][1] = dp[i-1][0]; dp[i][2] = 10 * dp[i-1][2] + dp[i-1][1]; } cin >> t; while(t --) { LL x; cin >> x; cout << cal(x+1) << endl; } return 0; }