HDU 6148 数位dp
2017-08-20 22:18
260 查看
题意:
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6148中文题。
思路:
dp[pos][pre][flag]表示当前dp到第pos位且前一个数位上的数字是pre方案数,flag为0表示当前处于递减阶段,flag=1表示递增阶段。dp很简单,但有两点需要注意,一个是前导零的处理,另一个是对于山谷转折点的处理,因为数字可以满足相邻的相同,所以在某一位决定转折(从递减到递增)的时候需要在下一位从pre+1开始枚举,因为如果从pre开始枚举,那与这一位不做转折点的情况一样了,会产生重复。代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; const LL mod = 1e9 + 7; LL dp[105][15][2][2]; int a[105]; LL dfs(int pos, int pre, int flag, bool limit, bool zero) { if (pos == -1) { if (zero) return 0; return 1; } if (!limit && dp[pos][pre][flag][zero] != -1) return dp[pos][pre][flag][zero]; LL res = 0; int up = limit ? a[pos] : 9; if (zero) { for (int i = 0; i <= up; i++) res = (res + dfs(pos - 1, i, 0, limit && a[pos] == i, i == 0)) % mod; } else { if (flag == 0) { for (int i = 0; i <= up && i <= pre; i++) res = (res + dfs(pos - 1, i, 0, limit && a[pos] == i, 0)) % mod; for (int i = pre + 1; i <= up; i++) res = (res + dfs(pos - 1, i, 1, limit && a[pos] == i, 0)) % mod; } else { for (int i = pre; i <= up; i++) res = (res + dfs(pos - 1, i, 1, limit && a[pos] == i, 0)) % mod; } } if (!limit) dp[pos][pre][flag][zero] = res; return res; } char str[105]; int main() { memset(dp, -1, sizeof dp); int T; scanf("%d", &T); while (T--) { scanf("%s", str); int len = strlen(str); for (int i = 0; i < len; i++) a[i] = str[len - i - 1] - '0'; LL ans = dfs(len - 1, 0, 0, 1, 1); printf("%I64d\n", ans); } return 0; }
相关文章推荐
- hdu 6148 数位DP(板子 递增递减
- hdu 6148 数位DP(板子 递增递减
- 2017"百度之星"程序设计大赛 - 复赛1005&&HDU 6148 Valley Numer【数位dp】
- hdu 6148 数位DP(板子 递增递减
- 【HDU-6148】 Valley Numer(数位dp)
- hdu 6148 数位DP(板子 递增递减
- hdu 6148 Valley Numer(数位DP)
- hdu 6148 数位DP(板子 递增递减
- HDU 6148 Valley Numer(数位DP)
- hdu 6148 数位DP(板子 递增递减
- 【HDU】6148 Valley Numer 数位DP
- [数位DP]Hdu 6148——Valley Number
- Hdu 6148 Valley Numer 数位DP
- hdu 6148 数位DP(板子 递增递减
- hdu 6148 数位DP(板子 递增递减
- HDU 6148 数位dp
- 2017百度之星复赛 hdu 6148 Valley Numer (数位dp)
- hdu 6148(数位dp)
- HDU 6148 数位dp
- hdu 6148 Valley Numer (数位dp)