问题
HDU 2089 不要62(数位dp) - https://acm.hdu.edu.cn/showproblem.php?pid=2089
分析
状态转移
从低位到高位
- 注意:图中的最高位是指当前已构造部分的最高位,并非指最终的最高位
从高位到低位
- 注意:图中的最低位是指当前已构造部分的最低位,并非指最终的最低位
状态设计
- 本题采用从低位到高位转移的方式
-
d
p
[
n
]
[
s
t
a
t
e
]
dp[n][state]
dp[n][state]:长度n位的数字在state条件下 不 含4和62的数字个数
- state = 0,表示所有不含4和62的数字个数
- state = 1,表示不是2开头的不含4和62的数字个数
参考
- 详细讨论请参考Bomb
代码
/* hdu 2089 不是62 数位dp*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MXN = 25;
int n, b[MXN];
ll dp[MXN][2];
ll dfs(int m, int is6, bool ismax){
if(m == 0) return 1;
if(!ismax && ~dp[m][is6]) return dp[m][is6];
ll ans = 0, end = ismax?b[m]:9;
for(int i = 0; i <= end; ++i){
if(i == 4 || (is6 && i == 2)) continue;
ans += dfs(m-1, i == 6, ismax && i == end);
}
if(!ismax) dp[m][is6] = ans;
return ans;
}
ll solve(ll num){
n = 0;
for(ll i = num; i > 0; i /= 10) b[++n] = i%10;
return dfs(n, 0, true);
}
int main(){
ll N, M;
memset(dp, -1, sizeof dp); // 仅初始化一次
while(scanf("%lld%lld", &N, &M)==2){
if(N == 0 && M == 0) break;
printf("%lld\n", solve(M)-solve(N-1));
}
return 0;
}