HDU 2089 不要62

不要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连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。
 

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));
    }
}



posted @ 2015-11-11 03:16  ChiLuManXi  阅读(122)  评论(0编辑  收藏  举报