不要62
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 18620 Accepted Submission(s): 6251
Problem Description
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。
Input
输入的都是整数对n、m(0<n≤m<1000000),如果遇到都是0的整数对,则输入结束。
Output
对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。
Sample Input
1 100 0 0
Sample Output
80
Author
qianneng
Source
Recommend
lcy
人生第一道数位DP,看着别人的代码写的,几乎是用抄的,但虽然这样,感觉还是增加了我对数位DP的理解。
其他地方网上各种题解都讲的很多,我只讲自己学到的东西。
要求从n到m的数中一共有多少个满足条件的,通常将这类问题拆成两个子问题,就是算出从0到n中有多少个满足条件的,再算出从0到m中有多少个满足条件的,最后将两个数一减即可,而这两个子问题都有相同的结构,处理办法都相同。
预处理的过程是计算出前i位数中满足条件的有几个,这里的前i位数可以有前导零,因为在后续的处理中,用到预处理结果的地方都不是最高位(比如说预处理结果存在数组dp[i][j]中,i表示位数,一般在处理最高位时调用的都是dp[i-1][j])。预处理的转移方程一般都是比较好确定的。
难得是后续处理,比如对于一个数4567,从它的最高位依次对它处理,第一位是4,通过预处理的结果可以知道0~3999中有多少个满足条件的数(当然可能还要经过其他一系列讨论),下一步处理它的下一位5,这次操作可以知道从4000~4499中有多少个满足条件的数,再下一步,能确定4500到4559中有多少满足条件的数,再下一步,4560~4566.9(这里的0.9就不会继续处理了)所以对一个数n,处理的结果是0~n(不包括n)中有多少满足条件的数,而不是0~n(包括n)中有多少满足条件的数。
代码:
#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MAXN 1000010
#define INF 2100000000
#define esp 1e-6
using namespace std;
long long dp[10][3];
int n, m;
long long bit[10];
long long solve(long long x)
{
int cnt = 0;
long long res = 0;
long long temp = x;
bool flag = false;
while(temp != 0)
{
bit[++cnt] = temp%10;
temp /= 10;
}
bit[cnt+1] = 0;
for(int i = cnt; i > 0; i--)
{
res += dp[i-1][2]*bit[i];
if(flag) res += dp[i-1][0]*bit[i];
if(!flag && bit[i] > 4) res += dp[i-1][0];
if(!flag && bit[i+1] == 6 && bit[i] > 2) res += dp[i][1];
if(!flag && bit[i] > 6) res += dp[i-1][1];
if(!flag && (bit[i] == 4 || (bit[i+1] == 6 && bit[i] == 2))) flag = true;
}
return x-res;
}
int main()
{
//freopen("C:/Users/Admin/Desktop/in.txt", "r", stdin);
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for(int i = 1; i < 10; i++)
{
dp[i][0] = dp[i-1][0]*9 - dp[i-1][1];
dp[i][1] = dp[i-1][0];
dp[i][2] = dp[i-1][2]*10 + dp[i-1][1] + dp[i-1][0];
}
while(cin >> n >> m)
{
if(n == 0 && m == 0) return 0;
long long a = solve(m+1) ;
long long b = solve(n);
printf("%lld\n", a-b);
}
return 0;
}