不要62
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 27541 Accepted Submission(s): 9672
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
题目意思很简单,就是求一段区间内不含62,不含4的数目的个数,这个题跟之前做的Bomb那个题基本上是相同的,这里给出三种方法。分别是暴力搜索,递推和记忆化搜索。前两者思路是和Bomb那个题相同的,暴力搜索字符串思想比较简单,耗时比较厉害。
暴力搜索:
/*************************************************************************
> File Name: do_not_want_62_by_itoa.cpp
> Author: Zhanghaoran
> Mail: chilumanxi@xiyoulinux.org
> Created Time: Tue 03 Nov 2015 10:33:48 PM CST
************************************************************************/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;
int ans[1000010];
void work(){
char str[10];
for(int x = 1; x <= 1000000; x ++){
sprintf(str, "%d", x);
if(strstr(str, "4") == NULL && strstr(str, "62") == NULL)
ans[x] = ans[x - 1] + 1;
else
ans[x] = ans[x - 1];
}
}
int main(void){
int a, b;
memset(ans, 0, sizeof(ans));
work();
while(1){
scanf("%d%d", &a, &b);
if(!a && !b)
break;
cout << ans[b] - ans[a - 1] << endl;
}
}
递推需要预处理的是dp数组,分别是不含62和不含4的数目,最高位为2且不含62的个数,最后是含62和4的个数
/*************************************************************************
> File Name: do_not_want_62.cpp
> Author: Zhanghaoran
> Mail: chilumanxi@xiyoulinux.org
> Created Time: Tue 03 Nov 2015 06:37:35 PM CST
************************************************************************/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;
int dp[8][3];
void init(){
dp[0][0] = 1;
dp[0][1] = 0;
dp[0][1] = 0;
for(int i = 1; i < 12; 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];
}
}
int make_num(long long x, int *num){
int len = 0;
while(x){
num[++ len] = x % 10;
x /= 10;
}
num[len + 1] = 0;
return len;
}
long long calc(long long x){
int num[8];
int len = make_num(x, num);
long long ans = 0;
bool flag = false;
for(int i = len; i >= 0; i --){
ans += num[i] * dp[i - 1][2];
if(flag){
ans += num[i] * dp[i - 1][0];
}
else{
if(num[i] > 4)
ans += dp[i - 1][0];
if(num[i + 1] == 6 && num[i] > 2)
ans += dp[i][1];
if(num[i] > 6)
ans += dp[i - 1][1];
}
if(num[i] == 4 || (num[i + 1] == 6 && num[i] == 2))
flag = true;
}
if(flag)
ans ++;
return x - ans;
}
int main(void){
init();
int a, b;
while(1){
scanf("%d%d", &a, &b);
if(!a && !b)
break;
cout << calc(b) - calc(a - 1) << endl;
}
}
记忆化搜索:
比递推好理解一些,跳过含62和4的即可。
/*************************************************************************
> File Name: do_not_want_62_dfs.cpp
> Author: Zhanghaoran
> Mail: chilumanxi@xiyoulinux.org
> Created Time: Wed 11 Nov 2015 01:38:37 AM CST
************************************************************************/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;
long long a, b;
long long dp[25][2];
int num[25];
long long work(int pos, bool fir_6, bool flag){
if(pos == 0)
return 1;
if(!flag && dp[pos][fir_6] != -1){
return dp[pos][fir_6];
}
long long ans = 0;
int temp = flag ? num[pos] : 9;
for(int i = 0; i <= temp; i ++){
if((fir_6 && i == 2) || i == 4)
continue;
ans += work(pos - 1, i == 6, flag && i == temp);
}
if(!flag)
dp[pos][fir_6] = ans;
return ans;
}
long long calc(long long x){
int i = 1;
while(x){
num[i ++] = x % 10;
x /= 10;
}
return work(i - 1, false, true);
}
int main(void){
memset(dp, -1, sizeof(dp));
while(1){
scanf("%lld%lld", &a, &b);
if(a == b && a == 0)
break;
printf("%lld\n", calc(b) - calc(a - 1));
}
}