HDU 3555:Bomb

  题目大意:求出1~n中含有“49”的数的个数。如n=500时:满足条件的有:"49","149","249","349","449","490","491","492","493","494","495","496","497","498","499"。答案为15。

  芒果君:初见这道题我有两个点没有想到解决方法,一个是上限的处理,一个是去重,甚至想到了容斥原理……web上的数位DP大多是顺推,而我误打误撞的找到了一个逆推的解法——找到不含“49”的数的个数,那么搜索就比较好做了(多组数据+重复决策明显记忆化)。但是还有些要注意的地方,我们对于上限的处理是比较因缺斯挺的,它也对决策有很大影响。还有必须保证答案的完整性才能记录,否则仅限当前的这个数(dfs的最后一条语句)。

  

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #define maxn 10010
 8 #define ll long long
 9 using namespace std;
10 int T,shu[20];
11 ll dp[20][2];
12 ll x;
13 ll dfs(int len,bool if_four,bool if_up)
14 {
15     if(!len) return 1;
16     if(!if_up&&dp[len][if_four]) return dp[len][if_four];
17     ll ret(0);
18     int up=(if_up?shu[len]:9);
19     for(int i=0;i<=up;++i){
20         if(if_four&&i==9) continue;
21         ret+=dfs(len-1,i==4,if_up&&i==up);
22     }
23     return if_up?ret:dp[len][if_four]=ret;
24 }
25 ll solve(ll x)
26 {
27     memset(shu,0,sizeof(shu));
28     int cnt(0);
29     while(x){
30         shu[++cnt]=x%10;
31         x/=10;
32     }
33     return dfs(cnt,0,1);
34 }
35 int main()
36 {
37     scanf("%d",&T);
38     while(T--){
39         scanf("%lld",&x);
40         printf("%lld
",x-solve(x)+1);
41     }
42     return 0;
43 }

  

原文地址:https://www.cnblogs.com/12mango/p/7415811.html