POJ 3286 How many 0's?(多少0?)
Posted Simon_X
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n", calculate(b) - calculate(a - 1)); 30 } 31 return 0; 32 }
以上是关于POJ 3286 How many 0's?(多少0?)的主要内容,如果未能解决你的问题,请参考以下文章
UVA - 10061 How many zero's and how many digits ?