• POJ 3286 How many 0's?(几多0?)


    POJ 3286 How many 0's?(几多0?)

    Time Limit: 1000MS   Memory Limit: 65536K

    【Description】

    【题目描述】

    A Benedict monk No.16 writes down the decimal representations of all natural numbers between and including m and n, m ≤ n. How many 0's will he write down?

    一个本尼迪克16号僧侣写下m与n之间并且包括mn的所有十进制自然数,m ≤ n。这之间他写下了多少个0?

    【Input】

    【输入】

    Input consists of a sequence of lines. Each line contains two unsigned 32-bit integers m and n, m ≤ n. The last line of input has the value of m negative and this line should not be processed.

    多组输入。每行有两个无符号32位整数m和n,m ≤ n。最后一行的m是负数,因此不该被执行。

    【Output】

    【输出】

    For each line of input print one line of output with one integer number giving the number of 0's written down by the monk.

    对于每行输入数据输出一行一个整数,表示这个僧侣写了多少个0.

    【Sample Input - 输入样例】

    【Sample Output - 输出样例】

    10 11

    100 200

    0 500

    1234567890 2345678901

    0 4294967295

    -1 -1

    1

    22

    92

    987654304

    3825876150

    【题解】

    如果不考虑数据范围,这道题应该就是入门级别的数位DP(此处可参考HDU 2089)

    不过这道的数据范围是unsigned int,无符号减法可能有问题,所以还是直接上int64吧。

    这道题在具体的思路上基本一致,因为数据范围大了,就需要压缩一下空间,不能任性。

    之后的计算方式大概可以变为:

    计算0~N写了几个0,即个位上0写的次数,十位上0…,百位上的0…以此类推。

    每一位按照其出现0的区间间隔与区间长度,计算这一位上写了几次0。

    百位

    [1000, 1099]

    [2000, 2099]

    [3000, 3099]

    [4000, 4099]

    ……

    十位

    [100, 109]

    [200, 209]

    [300, 309]

    [400, 409]

    ……

    个位

    [0, 0]

    [10, 10]

    [20, 20]

    [30, 30]

    ……

    以100为例:

      个位:直接100/10 +1 = 11(懒)。

      十位:100拆分成1 00

        其中1表示进位的次数,完整区间数1-0=1,剩余区间的元素个数 0–0+1=1。

        所以十位数的次数=0*10+1 = 1。

      百位:到达最高位,结束。

      结果:11+1 = 12。

    以200为例:

      个位:20 0,200/10 +1 = 21。

      十位:2 10,完整区间数2-1=1,剩余区间的元素个数0-0+1=10。

        剩余10>9,所以超过9的元素最多只能提供10个0

        十位数的次数=1*10+10 = 11。

      百位:结束。

      结果:21+11 = 32。

    其他数字的结果以此类推,就能计算0~N写了几个0。

    【代码 C++】

     1 #include<cstdio>
     2 __int64 cmp[12];
     3 void rdy(){
     4     int i;
     5     for (cmp[0] = i = 1; i < 12; ++i) cmp[i] = cmp[i - 1] * 10;
     6 }
     7 __int64 calculate(__int64 now){
     8     if (now < 0) return 0;
     9     int i = 1;
    10     __int64 right, left, opt = now / 10 + 1;
    11     while (1){
    12         left = now / (cmp[i + 1]);
    13         right = now % (cmp[i + 1]);
    14         if (right < now){
    15             opt += (left - 1)*(cmp[i]);
    16             if (right >= cmp[i]) opt += cmp[i];
    17             else opt += right + 1;
    18             ++i;
    19         }
    20         else break;
    21     }
    22     return opt;
    23 }
    24 int main(){
    25     rdy();
    26     __int64 a, b;
    27     while (scanf("%I64d%I64d", &a, &b)){
    28         if (a < 0) return 0;
    29         printf("%I64d
    ", calculate(b) - calculate(a - 1));
    30     }
    31     return 0;
    32 }
  • 相关阅读:
    oracle之bitmap索引
    oracle命令集
    Spring入门注解版
    spring入门一
    bootstrap栅格系统
    Struts2之基于配置的字段校验
    Struts2之文件上传下载
    Struts2之类范围拦截器和方法拦截器
    struts2之输入验证
    C++虚函数和纯虚函数的区别
  • 原文地址:https://www.cnblogs.com/Simon-X/p/5353491.html
Copyright © 2020-2023  润新知