AcWing 1085 不要62

题目描述:

杭州人称那些傻乎乎粘嗒嗒的人为 62(音:laoer)。

杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。

不吉利的数字为所有含有 4 或 62 的号码。例如:62315,73418,88914 都属于不吉利号码。但是,61152 虽然含有 6 和 2,但不是 连号,所以不属于不吉利数字之列。

你的任务是,对于每次给出的一个牌照号区间 [n,m],推断出交管局今后又要实际上给多少辆新的士车上牌照了。

输入格式

输入包含多组测试数据,每组数据占一行。

每组数据包含一个整数对 n 和 m。

当输入一行为“0 0”时,表示输入结束。

输出格式

对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。

数据范围

1≤n≤m≤10^9

输入样例:

1 100
0 0

输出样例:

80

分析:

方法一:动态规划 

本题同样是相当简单的数位DP问题,f[i][j]表示以j为开头的i位数中不含4和62数的个数。状态转移方程为f[i][j] += f[i-1][k],其中j != 4,k != 4,j等于6时k不能等于2。枚举每一位时,需要注意的是当n的当前位置数是4或者前面的一位是6,当前位是2时需要终止枚举。

#include <iostream>
#include <vector>
using namespace std;
const int N = 12;
int f[N][N];
void init(){
    for(int i = 0;i <= 9;i++)   f[1][i] = (i != 4);
    for(int i = 2;i < N;i++){
        for(int j = 0;j <= 9;j++){
            if(j == 4)  continue;
            for(int k = 0;k <= 9;k++){
                if(k!=4 && !(j==6&&k==2))   f[i][j] += f[i-1][k];
            }
        }
    }
}
int get(int n){
    if(!n)  return 1;
    vector<int> num;
    while(n)    num.push_back(n % 10),n /= 10;
    int res = 0,last = 0;
    for(int i = num.size() - 1;i >= 0;i--){
        int x = num[i];
        for(int j = 0;j < x;j++){
            if(j!=4 && !(last==6&&j==2))    res += f[i + 1][j];
        }
        if(x == 4 || (last == 6 && x==2))   break;
        if(!i)  res++;
        last = x;
    }
    return res;
}
int main(){
    int n,m;
    init();
    while(cin>>n>>m,n || m){
        cout<<get(m) - get(n-1)<<endl;
    }
    return 0;
}

方法二:记忆化搜索

本题的记忆化搜索也只用在上一题的dfs框架中略加修改即可实现功能。dfs的参数有u,pre以及flag,当当前枚举到的数是4或者当前枚举到的数是2并且上一位是6时就跳过即可。

#include <iostream>
#include <cstring>
using namespace std;
const int N = 12;
int len,num[N],f[N][100][2];
int dfs(int u,int pre,int flag){
    if(f[u][pre][flag] != -1) return f[u][pre][flag];
    if(!u)  return 1;
    int res = 0;
    for(int i = 0;i <= 9;i++){
        if(i == 4 || (pre==6 && i == 2))    continue;
        if(flag && i >= num[u]){
            if(i == num[u]) res += dfs(u - 1,i,1);
            break;
        }
        else    res += dfs(u - 1,i,0);
    }
    return f[u][pre][flag] = res;
}
int get(int n){
    if(!n)  return 1;
    len = 0;
    while(n)    num[++len] = n % 10,n /= 10;
    memset(f,-1,sizeof f);
    return dfs(len,0,1);
}
int main(){
    int a,b;
    while(cin>>a>>b,a || b){
        cout<<get(b) - get(a - 1)<<endl;
    }
    return 0;
}

 

AcWing 1085 不要62AcWing 1085 不要62 昂昂累世士 发布了311 篇原创文章 · 获赞 31 · 访问量 1万+ 私信 关注
上一篇:LeetCode 62


下一篇:62-函数的调用