hdu-2089 不要62 基础DP 模板
http://acm.hdu.edu.cn/showproblem.php?pid=2089
数位DP的思想时预处理以x开头长度为len的数(例如 x000~x999)的所有情况。给出一个数,可以在log10(n)的复杂度下完成分解。
#include <iostream> #include <cstring> #include <string> #include <queue> #include <vector> #include <map> #include <set> #include <stack> #include <cmath> #include <cstdio> #include <algorithm> #define LL long long using namespace std; const LL N = 1000015; const LL INF = 100000009; LL dp[8][10];//bit,num void init() { memset(dp, 0, sizeof dp);//初始化为0 LL sum = 0, temp = 0;//用sum维护上一层的总和,当传递不是简单的和传递时考虑用多维sum维护或者暴力 for (int i = 0; i < 10; i++) dp[0][i] = 1; dp[0][4] = 0; sum = 9; for (int len = 1; len < 8; len++) { temp = 0;//临时记录本层 for (int i = 0; i < 10; i++) { if (i == 4)continue; dp[len][i] = sum; if (i == 6) dp[len][i] -= dp[len - 1][2]; temp += dp[len][i]; } sum = temp; } } LL arr[100];//当前求解的数的分解 LL dfs(LL pos, LL pre) { if (pos == -1)return 0;//尾部 LL num = arr[pos];//获取当前数 LL cnt = 0;//计算以pre为前缀,后面从0~num-1开头的所有情况 for (int i = 0; i < num; i++) { if (pre == 6 && i == 2)continue; if (i == 4)continue; cnt += dp[pos][i]; } if (num == 4)return cnt; if (pre == 6 && num == 2)return cnt; return cnt + dfs(pos - 1, num);//下一级dfs传递前缀(对于不同题目需要传递的前缀信息不同) } LL sol(LL x) { x++;//dfs在求解时,只能解出x-1的所有情况,x需要在递归尾部特判,干脆我们将x++,这样正好求出x if (x == 0) return 1; LL siz = 0; while (x) arr[siz++] = x % 10, x /= 10; LL ans = 0; ans = dfs(siz - 1, -1); return ans; } int main() { cin.sync_with_stdio(false); LL n, m; init(); while (cin >> n >> m) { if (n == 0 && m == 0) break; cout << sol(m) - sol(n - 1) << endl; } return 0; }