/**
* 数位DP:
* 和HDU 3555类似,稍微复杂了点点,不同在于,
* 一、多考虑4的情况
* 二、因为子串是“62” 而3555的子串“49” 末尾数字不同
* 所以这题要多加一种情况if(num[i] > 2 && last == 6) //last 表示前一位数num[i+1]
* 状态还是一样:
* dp[i][0] 表示所有不含不吉利的数开头任意
* dp[i][1] 表示所有不含不吉利的开头为2的数
* dp[i][2] 表示所有含不吉利的数
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
#define DEBUG 0
#define INF 0x1fffffff
#define MAXN 100005
typedef long long LL;
using namespace std;
int dp[10][3];
int digit[10];
int cal(int x)
{
int cnt, ori, last, bad, ans;
memset(digit, 0, sizeof(digit));
bad = last = ans = cnt = 0;
ori = x;
while(x)
{
digit[++cnt] = x % 10;
x /= 10;
}
for(int i = cnt; i >= 1; i --)
{
ans += dp[i-1][2] * digit[i];
if(bad)
{
ans += digit[i] * dp[i-1][0];
}
else
{
if(digit[i] > 4) ans += dp[i-1][0];
if(digit[i] > 6) ans += dp[i-1][1];
if(last == 6 && digit[i] > 2)
ans += dp[i][1];
}
if(last == 6 && digit[i] == 2 || digit[i] == 4)
bad = true;
last = digit[i];
}
return ori - ans;
}
int main()
{
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for(int i = 1; i <= 8; i ++)
{
dp[i][0] = dp[i-1][0] * 9 - dp[i-1][1];
dp[i][1] = dp[i-1][0];
dp[i][2] = 10 * dp[i-1][2] + dp[i-1][0] + dp[i-1][1];
}
int a, b;
while(scanf("%d%d", &a, &b), a+b)
{
printf("%d\n", cal(b+1) - cal(a));
}
return 0;
}
HDU 2089 数位dp (简单)
最新推荐文章于 2019-04-15 09:38:10 发布