数位dp

含有一个数字(4)或者一个数(62)

对于找这些问题就是:首先dp[]的一维就是这个数的位数,1类问题本质就是在寻找某个状态,所以需要加上状态一维,此时dp[][] 就存在了二维, 数位dp实质就是暴力,因为一般的数位dp是借助dfs的搜索方式来完成的,dfs的工作就是像一颗只有主干和根的树,从主干直接去往根部走,先按照一个根以及这个根的一个分支往下走。遇到符合情况的就改变此时的状态,直到pos<0时,dfs完成了一种情况的搜索, 然后记录结果,继续往下一个分支走,当所有的分支遍历过后,工作完成

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <cstring>
 5 #include <algorithm>
 6 #include <queue>
 7 #include <map>
 8 #include <set>
 9 #define ll long long
10 using namespace std;
11 const int maxn = 1e5;
12 ll num[20];///直接找数据范围就行
13 ll dp[20][3];///一维代表位数,二维代表状态
14 ll dfs(int pos,int state,int limt)
15 {
16     if(pos < 0)///搜索完所有的位数时返回
17         return state == 2;
18     if(!limt && dp[pos][state]!=-1)///记忆化搜索的返回条件,大量节省时间,没有这一步记忆化就起不上作用了
19         return dp[pos][state];
20     int up = limt?num[pos]:9;/// up 在这一位上的最大值
21     ll ans=0;
22     for(int i=0; i<=up; i++)
23     {
24         if(i == 4 || state == 2 || i==2 && state == 1)
25             ans += dfs(pos-1, 2, i==up&&limt);
26         else if(i==6)
27             ans += dfs(pos-1, 1, i==up&&limt);
28         else
29             ans += dfs(pos-1, 0, i==up&&limt);
30         ///关于i==up&&limt这一步的理解,现在的条件是不是满足这个式子,yes or no?1:0;
31         
32         ///和上面判断条件一样,形式不一样,意思一样
33         /**if(i == 4 || state == 2 || i==2 && state == 1)
34             state2 = 2;///这个状态是重新定义的,不能在state上面直接改,否则后面的for循环的state状态就不符合原来的状态了
35         else if(i==6)
36             state2 = 1;
37         else
38             state2 = 0;
39         ans += dfs(pos-1, state2, i==up&&limt);*/
40     }
41     ///记忆化需要先记忆,在调用,这里就是
42     if(!limt)///没达到最大值时,调用,因为每个情况的最大值不同,最大值处的值不存在记录意义
43         dp[pos][state] = ans;
44     return ans;
45 }
46 
47 ll Solve(ll as)
48 {
49     int len = 0;
50     memset(dp, -1, sizeof(dp));
51     memset(num, -1, sizeof(num));
52     while(as)
53     {
54         num[len++] = as%10;
55         as /= 10;
56     }
57     return dfs(len-1, 0, 1);///*****
58 }
59 
60 int main()
61 {
62     ll n, m;
63     while(scanf("%lld %lld", &n, &m),n+m)
64     {
65         ll ans = Solve(m) - Solve(n-1);
66         cout<<m - n + 1 - ans<<endl;
67     }
68     return 0;
69 }
View Code

 

posted @ 2018-07-25 10:45  _簡單é  阅读(90)  评论(0编辑  收藏  举报