[hdu 4734]数位dp例题
通过这个题目更加深入了解到了数位dp在记忆化搜索的过程中就是实现了没有限制条件的n位数的状态复用。
#include<bits/stdc++.h> using namespace std; int f2[20]; int b[20]; int dp[20][4700]; int A; int F(int x) { int a[20]; int cnt=0; int ret=0; do{ a[cnt]=x%10; x/=10; cnt++; }while (x); for (int i=cnt-1;i>=0;i--) { ret=ret*2+a[i]; } return ret; } 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 (limit-f2[pos]*i<0) continue; if (i<b[pos]||preok) ans+=dfs(pos-1,1,limit-f2[pos]*i); else ans+=dfs(pos-1,0,limit-f2[pos]*i); } 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,F(A)); } int main() { memset(dp,-1,sizeof(dp)); f2[0]=1; for (int i=1;i<=20;i++) f2[i]=f2[i-1]*2; int t; scanf("%d",&t); for (int cas=1;cas<=t;cas++) { int n; scanf("%d%d",&A,&n); printf("Case #%d: %d\n",cas,solve(n)); } return 0; }