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\n",x-solve(x)+1); 41 } 42 return 0; 43 }