• HDU 3555 Bomb


    Bomb

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


    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.
     
    第一次接触数位DP题目,不太明白到底什么是数位DP,看了看题解,好像有点感觉。

    题目意思是给定一段区间,求数字中含有49的数的个数。

    首先显然需要将这个数按位存储在

    建立数组dp[25][3],dp[i][0]表示到第i个位置的没有49的个数

    dp[i][1]表示到第i个位置的没有49但是最高位是9的数的个数,像9,90,91,92,93,94,95,96,97,98,99这些都是。之所以统计这一项是因为只要在下一位添加4,就可以组成这些数个49

    dp[i][2]表示到第i个位置的含49的数的个数

    那么经过预处理以后,我们就可以得到一个位数这三项的个数,然后我们根据所给的数字就可求出对应的49的个数,方法如下:

    我们仍从低位向高位进行分析,首先ans加上到第i位含49的数的个数,然后进行分析如果这个数当前位数大于4的话,加上所有该位第一位的dp[i][1]的数目乘以该数,这说明在当前位数的数量级下有的49的个数(因为高位大于了4),最后如果出现49含有的话,每一次除了加上上一位时所有含49的,还需要加上所有不是49的数的个数,因为有了49,高位无论加上什么数他都是含有49的。

    代码如下,很好理解:flag表示是否出现了49

    /*************************************************************************
    	> File Name: Bomb.cpp
    	> Author: Zhanghaoran
    	> Mail: chilumanxi@xiyoulinux.org
    	> Created Time: Tue 03 Nov 2015 06:01:49 PM CST
     ************************************************************************/
    
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    
    using namespace std;
    
    int num[25];
    long long dp[25][3];
    int T;
    long long x;
    void init(){
        dp[0][0] = 1;
        dp[0][1] = 0;
        dp[0][2] = 0;
        for(int i = 1; i < 25; i ++){
            dp[i][0] = dp[i - 1][0] * 10 - dp[i - 1][1];
            dp[i][1] = dp[i - 1][0];
            dp[i][2] = dp[i - 1][2] * 10 + dp[i - 1][1];
        }
    }
    
    
    int make_num(long long x){
        int len = 0;
        while(x){
            num[++ len] = x % 10;
            x /= 10;
        }
        num[len + 1] = 0;
        return len;
    }
    
    int main(void){
        scanf("%d", &T);
        init();
        while(T --){
            cin >> x;
            int len = make_num(x);
            bool flag = false;
            long long ans = 0;
            for(int i = len; i >= 1; i --){  //1449 -> 9441
                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][1];
                    }
                }
                if(num[i + 1] == 4 && num[i] == 9)
                    flag = true;
            }
            if(flag){
                ans ++;
            }
            cout << ans << endl;
        }
    }
    有做Beautiful numbers那个题,很自然的想到是否用DFS记忆搜索dp可以做。显然也是没有问题的。

    加两个判断条件,一个是判断是否到达上限,一个判断最高位是否是4

    代码:

    /*************************************************************************
    	> File Name: Bomb_dfs.cpp
    	> Author: Zhanghaoran
    	> Mail: chilumanxi@xiyoulinux.org
    	> Created Time: Tue 10 Nov 2015 07:43:05 PM CST
     ************************************************************************/
    
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    
    int T;
    long long N;
    long long dp[25][2];
    int num[25];
    
    long long work(int pos, bool fir_4, bool max){
        if(pos == 0){
            return 0;
        }
        if(!max && dp[pos][fir_4]){
            return dp[pos][fir_4];
        }
    
        long long ans = 0;
        int flag = max ? num[pos] : 9;
        for(int i = 0; i <= flag; i ++){
            if(fir_4 && i == 9){
                long long di = pow(10, pos - 1);
                ans += max ? N % di + 1 : di;
            }
            else{
                ans += work(pos - 1, i == 4, max && num[pos] == i);
            }
        }
    
        if(!max)
            dp[pos][fir_4] = ans;
        return ans;
    }
    
    long long calc(long long N){
        int i  = 1;
        while(N){
            num[i ++] = N % 10;
            N /= 10;
        }
        return work(i - 1, false, true);
    }
    
    int main(void){
        scanf("%d", &T);
        while(T --){
            scanf("%lld", &N);
            cout << calc(N) << endl;
        }
        return 0;
    }



  • 相关阅读:
    Python学习笔记:List类型所有方法汇总
    Python学习笔记:String类型所有方法汇总
    制作“铜墙铁壁”一样的比特币冷钱包的完整流程详解!!
    jpa教程+ 常见的jpa报错以及解决方式
    Hibernate之mappedBy与@JoinColumn
    什么是JPA?Java Persistence API简介
    一文搞懂并发和并行
    清华大学操作系统【mark下】
    一文足以了解什么是 Java 中的锁.
    JDK8日常开发系列:Consumer详解
  • 原文地址:https://www.cnblogs.com/chilumanxi/p/5136062.html
Copyright © 2020-2023  润新知