[hdu 2089]简单数位dp
一个不错的讲解数位dp的博客:http://blog.csdn.net/wust_zzwh/article/details/52100392
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089
这个题数据范围比较小,所以暴力也可以过,像这样:
#include<bits/stdc++.h> using namespace std; const int maxn=1000005; int a[maxn]; bool laoer(int x) { int b[10]={}; int cnt=0; do{ b[cnt]=x%10; x/=10; cnt++; }while (x); for (int i=0;i<cnt;i++) { if (b[i]==4||b[i]==2&&b[i+1]==6) return true; } return false; } int main() { for (int i=1;i<=1000000;i++) { if (laoer(i)) a[i]=1; a[i]+=a[i-1]; } int n,m; while (~scanf("%d%d",&n,&m) && (n||m)) { printf("%d\n",(m-n+1)-(a[m]-a[n-1])); } return 0; }
但是还是数位dp的方法更厉害一点。实质上就是对于一个给定的范围,用记忆化搜索搞出来。
#include<bits/stdc++.h> using namespace std; int b[20]; int dp[20][2]; int dfs(int pos,int preok,int limit) { if (pos==-1) return 1; if (preok && dp[pos][limit]!=-1) return dp[pos][limit]; int up=preok?9:b[pos]; int ans=0; for (int i=0;i<=up;i++) { if (i==4||limit&&i==2) continue; if (i<b[pos]||preok) ans+=dfs(pos-1,1,i==6); else ans+=dfs(pos-1,0,i==6); } if (preok) dp[pos][limit]=ans; return ans; } int solve(int n) { if (n<0) return 0; int cnt=0; int now=n; do{ b[cnt]=now%10; now/=10; cnt++; }while (now); return dfs(cnt-1,0,0); } int main() { memset(dp,-1,sizeof(dp)); int n,m; while (~scanf("%d%d",&n,&m) && (n||m)) { printf("%d\n",solve(m)-solve(n-1)); } return 0; }