HDU 3555 Bomb 数位dp
2017-09-14 16:58
337 查看
题目:
http://acm.hdu.edu.cn/showproblem.php?pid=3555题意:
多组测试数据,每次一个n,问1到n范围内子串中有49的数字的个数思路:
简单数位dp?个人觉得数位dp其实就是个记忆化搜索,第一次写,看了一下别人代码,有不同的写法//300+ms #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 50 + 10, INF = 0x3f3f3f3f; ll dp [10][2]; //dp[i][j][k]:在无限制取值范围条件下第i位后前驱为j时状态为k时的方案数 int dig ;//分离后的数字 ll dfs(int pos, int pre, int status, int limit) {//pos是当前处理的位置,pre是前一个处理的位上的数字,status是有没有已经出现了49这个子串,limit表示对于当前位数字的取值范围有没有限制 if(pos < 0) return status; if(! limit && dp[pos][pre][status] != -1) return dp[pos][pre][status]; int en = limit ? dig[pos] : 9; ll ans = 0; for(int i = 0; i <= en; i++) ans += dfs(pos-1, i, status || (pre == 4 && i == 9), limit && i == en); if(! limit) dp[pos][pre][status] = ans; return ans; } int main() { int t; ll n; scanf("%d", &t); while(t--) { scanf("%lld", &n); int tot = 0; while(n) dig[tot++] = n % 10, n /= 10; memset(dp, -1, sizeof dp); ll ans = dfs(tot-1, 0, 0, 1); printf("%lld\n", ans); } return 0; }
//70ms #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 30 + 10, INF = 0x3f3f3f3f; ll dp [2]; ll p ; int dig ; ll n; void table() { p[0] = 1; for(int i = 1; i < N; i++) p[i] = p[i-1] * 10; } ll dfs(int pos, bool is4, bool limit) { if(pos < 0) return 0; if(! limit && dp[pos][is4] != -1) return dp[pos][is4]; int en = limit ? dig[pos] : 9; ll ans = 0; for(int i = 0; i <= en; i++) if(is4 && i == 9) ans += limit ? n % p[pos] + 1 : p[pos];//直接计算无需递归,效率提升很多 else ans += dfs(pos-1, i == 4, limit && i == en); if(! limit) dp[pos][is4] = ans; return ans; } int main() { table(); int t; scanf("%d", &t); while(t--) { scanf("%lld", &n); ll m = n; int k = 0; while(m) dig[k++] = m % 10, m /= 10; memset(dp, -1, sizeof dp); ll ans = dfs(k-1, 0, 1); printf("%lld\n", ans); } return 0; }
//这个是求不含49的个数,然后用总数减去 #include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 30 + 10, INF = 0x3f3f3f3f; ll dp [2]; ll p ; int dig ; ll n; void table() { p[0] = 1; for(int i = 1; i < N; i++) p[i] = p[i-1] * 10; } ll dfs(int pos, bool is4, bool limit) { if(pos < 0) return 1; if(! limit && dp[pos][is4] != -1) return dp[pos][is4]; int en = limit ? dig[pos] : 9; ll ans = 0; for(int i = 0; i <= en; i++) if(is4 && i == 9) ans += 0; else ans += dfs(pos-1, i == 4, limit && i == en); if(! limit) dp[pos][is4] = ans; return ans; } int main() { table(); int t; scanf("%d", &t); while(t--) { scanf("%lld", &n); ll m = n; int k = 0; while(m) dig[k++] = m % 10, m /= 10; memset(dp, -1, sizeof dp); ll ans = dfs(k-1, 0, 1); printf("%lld\n", n - ans + 1); } return 0; }
相关文章推荐
- HDU 3555 Bomb (数位dp)
- HDU 3555 Bomb(数位DP)
- HDU - 3555 bomb(数位DP) HQG_AC的博客
- HDU-3555 Bomb (数位DP)
- HDU 2089 不要62 && HDU 3555 Bomb (数位DP)
- hdu 3555 Bomb【数位dp~吖!!!!!】
- 【数位dp】HDU - 3555 Bomb
- HDU 3555 Bomb(数位DP)
- HDU 3555 Bomb (数位DP)
- HDU 3555 Bomb 简单数位DP
- HDU 3555 Bomb [数位DP]【动态规划】
- HDU-3555 Bomb 数位DP
- hdu 3555 Bomb (数位DP)
- hdu 3555 Bomb(数位dp)
- HDU-3555-Bomb【数位dp】
- hdu 3555 bomb 数位dp
- 数位DP——Bomb ( HDU 3555 )
- hdu 3555 Bomb ( 数位DP)
- hdu-3555 Bomb(数位dp)
- HDU 3555 Bomb ,HDU 2089 深刻学习数位dp (各种方法乱用)