HDU3555 区间的数里面有49的个数(数位dp)
题目:区间的数里面有49的个数
分析:
dp[pos][0]:长度为pos的数中,不包含49的,前一位不为4的有多少个;
dp[pos][1]:长度为pos的数中,不包含49的,前一位为4的有多少个;
dp[pos][2]:长度为pos的数中,包含49的有多少个;
一开始我是打算先算不满足的,在算满足的;结果不行,可能这样算出来的数太大了所以不行吧;
通过这道题可以更加理解了(不要62)这个题目的sta 的表示 , 原来如此呀
#include<stdio.h> #include<string.h> using namespace std; typedef long long ll; int dig[20]; ll dp[20][3]; /* dp[pos][0]:长度为pos的数中,不包含49的,前一位不为4的有多少个; dp[pos][1]:长度为pos的数中,不包含49的,前一位为4的有多少个; dp[pos][2]:长度为pos的数中,包含49的有多少个; */ ll dfs(int pos,int pre,bool have49,bool limit) { if(pos==0) return have49; if(!limit)//首先满足没有上界限制 { if(have49 && ~dp[pos][2]) return dp[pos][2]; if(!have49 && pre==4 && ~dp[pos][1]) return dp[pos][1]; if(!have49 && pre!=4 && ~dp[pos][0]) return dp[pos][0]; } int up=limit?dig[pos]:9; ll ans=0; for(int i=0;i<=up;i++) { if(pre==4 && i==9) ans+=dfs(pos-1,i,1,limit && i==up); else ans+=dfs(pos-1,i,have49,limit && i==up); } if(!limit) { if(have49) dp[pos][2]=ans; else { if(pre==4) dp[pos][1]=ans; else dp[pos][0]=ans; } } return ans; } ll solve(ll x) { int pos=0; while(x) { dig[++pos]=x%10; x/=10; } return dfs(pos,0,0,1); } int main() { int T; ll N; scanf("%d",&T); while(T--) { scanf("%I64d",&N); memset(dp,-1,sizeof(dp)); printf("%I64d\n",solve(N)); } }