Description
Input
Output
Sample Input
1 100 0 0
Sample Output
80
这题搞了两天了……才明白数位DP是什么意思,而且该怎么解……模板每一句话的意思与作用……
下面是数位通用模板的代码与解释:
int dfs(int i, int s, bool e) { if (i==-1) return s==target_s; if (!e && ~f[i][s]) return f[i][s]; int res = 0; int u = e?num[i]:9; for (int d = first?1:0; d <= u; ++d) res += dfs(i-1, new_s(s, d), e&&d==u); return e?res:f[i][s]=res; }f为记忆化数组; i为当前处理串的第i位(权重表示法,也即后面剩下i+1位待填数); s为之前数字的状态(如果要求后面的数满足什么状态,也可以再记一个目标状态t之类,for的时候枚举下t); 在这题中s==0时表示即不含有6和4的,s==1时表示含有6不含有4的,s==2时表示含有4或者62的 e表示之前的数是否是上界的前缀(即后面的数能否任意填)。#include <iostream> #include <map> #include <deque> #include <queue> #include <stack> #include <string> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <map> #include <set> using namespace std; int n,m,f[10][10],num[10]; int dfs(int i,int s,bool e) //i为第几个数,s为每个数的状态,在本题中共设0,1,2三个状态,上面已经说过 { if(i==-1) return 1; //因为4和62的情况continue掉了,所以返回s==0||s==1肯定是真的,真就是返回1 if(!e&&f[i][s]!=-1) return f[i][s]; //记忆哪个数时前面已经有多少个符合的数,直接返回就行 int res=0; int u=e?num[i]:9; //下一个数可以取多少 for(int d=0; d<=u; ++d) //有时候d不得取0,那么判断一下看看得不得取 { if(s==6&&d==2) continue; else if(d==4) continue; else res+=dfs(i-1,d,e&&d==u); } return e?res:f[i][s]=res; } int open(int x) { int k=0; while(x) { num[k++]=x%10; //从后往前取每位的数存入数组中 x/=10; } return k; } int gets(int n) { int mm=open(n); return dfs(mm-1,0,1); } void solve() { printf("%d\n",(gets(m)-gets(n-1))); } int main() { memset(f,-1,sizeof(f)); while(scanf("%d%d",&n,&m)&&(n||m)) solve(); return 0; }