不要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 ", calc(b) - calc(a - 1)); } }