链接
Click here to see the original question
题目描述
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。
输入
输入的都是整数对n、m(0<n≤m<1000000),如果遇到都是0的整数对,则输入结束。
输出
对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。
代码
#include <bits/stdc++.h>
using namespace std;
int n, m, bit[11], dp[11][2];
int DFS(int pos, bool isSix, bool isMax) {
//pos表示当前遍历的位数,isSix表示上一位是否为6,isMax表示上一位的值是否为相应的最大可能值
if(pos == 0) return 1;
//已经把所有的位数都遍历完毕,确定了一种可行方案
if(!isMax && dp[pos][isSix]) return dp[pos][isSix];
//若当前pos的值不是当前位的最大可能值
//那么相应的答案是可以重复利用的,dp[pos][isSix] != 0 就保证了这个数在之前已经计算过了,直接返回就好
//比如说,对于区间0 - 567, 100、200、300的种类数其实是一样的
//答案又分为上一位是6和不是6两种情况,要分开存储起来
int cnt = 0;//用来存储种类数
int maxNum = isMax ? bit[pos] : 9;
//区间0 - 567 , pos = 3 时, 如果当前已经遍历到5了,那么枚举下一位的时候最大值只能到6
for(int i = 0; i <= maxNum; i++){
if(i == 4 || (isSix && i == 2)) continue;//过滤掉不合法的情况
cnt += DFS(pos - 1, i == 6, isMax && i == maxNum);
}
return isMax ? cnt : dp[pos][isSix] = cnt;
//isMax为true时,没有存储的必要,比如对区间0 - 567,我们没必要把500-567区间的数据存储起来
}
int tran(int num) {
int pos = 0;
while(num){
bit[++pos] = num % 10;
num /= 10;
}
return DFS(pos, false, true);
}
int main() {
while(cin >> n >> m){
if(n == 0 && m == 0) break;
cout<<tran(m) - tran(n - 1)<<endl;
}
return 0;
}
如果您觉得我的文章对您有帮助的话,可以点个赞,点个关注,也可以扫描下方二维码关注我。我将在这个公众号上更新自己的学习笔记,以及分享一些算法知识
Study and progress together with me!