以前一直不知道该咋搞这个比较好。
感觉推起来那个数字好麻烦。后来有一种比较好的写法就是直接的DFS写法。相应的ismax表示当前位是否有限制。
数位DP也是有一种类似模版的东西,不过需要好好理解。与其他模版不同。
主要还是状态的定义
模版就不整理了。直接上题。
另外这里有一道题是数位DP+自动机的放到自动机里做
HDU 2089 不要62
基本的数位DP可以用来理解DFS写法
#include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 15; int dp[MAXN][2]; int digit[MAXN],length; int calcu(int len,bool issix,bool ismax) { if (len == 0) return 1; if (!ismax && dp[len][issix] != -1) return dp[len][issix]; int limit = ismax ? digit[len] : 9; int tot = 0; for (int i = 0 ; i <= limit ; i++) { if ((issix && i == 2) || i == 4 ) continue; tot += calcu(len - 1,i == 6 ,ismax && i == limit); } if (ismax) return tot; else return dp[len][issix] = tot; } int slove(int x) { int len = 0; int num = x; while (num) { digit[++len] = num % 10; num /= 10; } return calcu(len,false,true); } int main() { memset(dp,-1,sizeof(dp)); int l,r; while (scanf("%d%d",&l,&r) != EOF) { if (l == 0 && r == 0) break; if (l > r) swap(l,r); printf("%d\n",slove(r) - slove(l - 1)); } return 0; }