zoukankan      html  css  js  c++  java
  • HDU 2089 HDU3555 数位DP

    HUD 2089

    不要62

    Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 43142    Accepted Submission(s): 15815

    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

    Author

    qianneng

    做法一:

    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    using namespace std;
    
    int dp[10][3];
    
    void init()
    {
        int len = 6;
        memset(dp, 0, sizeof(dp));
        dp[0][0] = 1;
        for(int i = 1; i <= len; i++)
        {
            dp[i][0] = dp[i-1][0] * 9 - dp[i-1][1]; //首位不放4 不在次位是2的情况下放6
            dp[i][1] = dp[i-1][0];//首位放的是2
            dp[i][2] = dp[i-1][2] * 10 + dp[i-1][1] + dp[i-1][0]; //在2前面放6、放4 或者 在不合格的情况下随便放
        }
    }
    
    int solve(int x)
    {
        int a[10],n = x, ans = 0;
        int len = 0;
        int flag = 0;
        while (x)
        {
            a[++len] = x%10;
            x /= 10;
        }
        a[len + 1] = 0;
        for(int i = len; i >= 1; i--)
        {
            ans += dp[i-1][2] * a[i];
            if(flag)
            {
                ans += dp[i-1][0] * a[i];
            }
            if(!flag && a[i] > 4)
            {
                ans += dp[i-1][0];
            }
            if(!flag && a[i+1] == 6 && a[i] > 2)
            {
                ans += dp[i][1];
            }
            if(!flag && a[i] > 6)
            {
                ans += dp[i-1][1];
            }
            if(a[i] == 4 || (a[i] == 2 && a[i+1] == 6))
            {
                flag = 1;
            }
        }
        return n - ans;
    }
    
    int main()
    {
        int l, r;
        init();
        while(scanf("%d%d", &l, &r), l || r)
        {
            printf("%d
    ", solve(r + 1) - solve(l));
        }
        return 0;
    }

    做法二(记忆化搜索):

    #include <iostream>
    #include <string.h>
    #include <stdio.h>
    using namespace std;
    
    int a[10];
    int dp[10][2];
    
    int dfs(int pre, int pos, int status, bool limit)
    {
        if(pos == 0) return 1;
        if(!limit && dp[pos][status] != -1) return dp[pos][status];
        int up = limit ? a[pos] : 9;
        int ans = 0;
        for(int i = 0; i <= up; i++)
        {
            if(i == 4 ) continue;
            if(pre == 6 && i == 2) continue;
            ans += dfs(i, pos-1, i == 6, limit && i == up);
        }
        if(!limit) dp[pos][status] = ans;
        return ans;
    }
    
    int solve(int x)
    {
        int len = 0;
        memset(dp, -1, sizeof(dp));
        while(x)
        {
            a[++len] = x%10;
            x /= 10;
        }
        return dfs(-1, len, 0, true);
    }
    
    int main()
    {
        int l, r;
        while(scanf("%d%d", &l, &r), l || r)
        {
            printf("%d
    ", solve(r) - solve(l - 1));
        }
        return 0;
    }

    有了上面的思路,可以解决其他类似的问题。

    HDU 3555 试试水

    Bomb

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)
    Total Submission(s): 18374    Accepted Submission(s): 6781

    Problem Description

    The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the time bomb. The number sequence of the time bomb counts from 1 to N. If the current number sequence includes the sub-sequence "49", the power of the blast would add one point.
    Now the counter-terrorist knows the number N. They want to know the final points of the power. Can you help them?

    Input

    The first line of input consists of an integer T (1 <= T <= 10000), indicating the number of test cases. For each test case, there will be an integer N (1 <= N <= 2^63-1) as the description.
    The input terminates by end of file marker.

    Output

    For each test case, output an integer indicating the final points of the power.

    Sample Input

    3 1 50 500

    Sample Output

    0 1 15

    Hint

    From 1 to 500, the numbers that include the sub-sequence "49" are "49","149","249","349","449","490","491","492","493","494","495","496","497","498","499", so the answer is 15.

    Author

    fatboy_cw@WHU

    做法一:

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    using namespace std;
    typedef long long LL;
    
    LL dp[30][3];
    int a[30];
    
    void init()
    {
        memset(dp, 0, sizeof(dp));
        dp[0][0] = 1;
        for(int i = 1; i <= 25; i++)
        {
            dp[i][0] = dp[i-1][0] * 10 - dp[i-1][1]; //减去首位是6 次位是2
            dp[i][1] = dp[i-1][0];        //首位是2
            dp[i][2] = dp[i-1][2] * 10 + dp[i-1][1];//加上首位是6 次位是2
        }
    }
    
    LL solve(LL x)
    {
        int len = 0;
        while(x)
        {
            a[++len] = x%10;
            x /= 10;
        }
        a[len + 1] = 0;
        LL ans = 0LL;
        bool flag = false;
        for(int i = len; i >= 1; i--)
        {
            ans += dp[i-1][2] * a[i];
            if(flag)
                ans += dp[i-1][0] * a[i];
            if(!flag && a[i] > 4)
                ans += dp[i-1][1];
            if(a[i+1] == 4 && a[i] == 9)
                flag = true;
        }
        return ans;
    }
    
    int main()
    {
        init();
        int q;
        LL n;
        scanf("%d", &q);
        while(q--)
        {
            scanf("%lld
    ", &n);
            printf("%lld
    ", solve(n+1));
        }
        return 0;
    }

    做法二(记忆化搜索):

    #include <iostream>
    #include <string.h>
    #include <stdio.h>
    typedef long long LL;
    int a[30];
    LL dp[30][3];
    
    LL dfs(int pre, int pos, int status, bool limit)
    {
        if(pos == 0) return status == 2;
        if(!limit && dp[pos][status] != -1)
        {
            return dp[pos][status];
        }
        LL ans = 0LL;
        int up = limit ? a[pos] : 9;
        for(int i = 0; i <= up; i++)
        {
            int nstatus;
            if(status == 2 || pre == 4 && i == 9)
                nstatus = 2;
            else if(i == 4)
                nstatus = 1;
            else
                nstatus = 0;
            ans += dfs(i, pos-1, nstatus, limit && i == up);
        }
        if(!limit) dp[pos][status] = ans;
        return ans;
    }
    
    LL solve(LL x)
    {
        LL n = x, len = 0;
        memset(dp, -1, sizeof(dp));
        while(x)
        {
            a[++len] = x%10;
            x /= 10;
        }
        a[len + 1] = 0;
        return dfs(-1, len, 0, true);
    }
    
    
    int main()
    {
        LL n;
        int q;
        scanf("%d", &q);
        while(q--)
        {
            scanf("%lld", &n);
            printf("%lld
    ",solve(n));
        }
        return 0;
    }
    如果有错误,请指出,谢谢
  • 相关阅读:
    git rebase解决合并冲突
    Google GMS介绍
    MTK Android修改System分区
    Adb adb push (remote write failed: No space left on device)
    Android Visibility控件显示和隐藏
    MTK Android中设置默认时区
    初级Oracle和SQL学习者的学习笔记。韩顺平-玩转oracle。
    网络知识从零开始一:私有地址。
    oracle中有关用户、角色的一些概念。
    oracle中的一些函数笔记
  • 原文地址:https://www.cnblogs.com/Alruddy/p/7113860.html
Copyright © 2011-2022 走看看