剑指Offer - 九度1373 - 整数中1出现的次数(从1到n整数中1出现的次数)

剑指Offer - 九度1373 - 整数中1出现的次数(从1到n整数中1出现的次数)
2014-02-05 23:03
题目描述:

亲们!!我们的外国友人YZ这几天总是睡不好,初中奥数里有一个题目一直困扰着他,特此他向JOBDU发来求助信,希望亲们能帮帮他。问题是:求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有110111213因此共出现6,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。

输入:

输入有多组数据,每组测试数据为一行。

每一行有两个整数a,b(0<=a,b<=1,000,000,000)

输出:

对应每个测试案例,输出ab之间1出现的次数。

样例输入:
0 5
1 13
21 55
31 99
样例输出:
1
6
4
7
题意分析:
  对于给定的整数a和b,求出从a到b所有整数中,数字‘1’出现的次数。
  这题显然不会让我们逐个统计每个数字中‘1’出现的次数,太慢了。
  可以按照位数从低往高进行递推:
    1. 定义所有n位数中(也包括1位、2位、...、n-1位)‘1’总共出现了f[n]次。
    2. f[0] = 0
    3. f[n+1]=10*f[n]+10^n。多出来的10^n表示最高位为‘1’的10^n个数。
  有了这个f[n]后,可以以log10(n)的复杂度递归求出从1~n中‘1’出现的次数。然后对a、b求解后求出差即可。要注意,a和b指不定谁大,必要的时候交换一下。
  时间复杂度O(log10(a) + log10(b))。空间复杂度O(log10(max(a,b))),虽然接近常数,但也不能写成O(1)哦。
剑指Offer - 九度1373 - 整数中1出现的次数(从1到n整数中1出现的次数)
 1 // 688882    zhuli19901106    1373    Accepted    点击此处查看所有case的执行结果    1020KB    1161B    0MS
 2 // 201402020057
 3 #include <cstdio>
 4 using namespace std;
 5 
 6 long long int sum[11];
 7 
 8 long long int solve(long long int x)
 9 {
10     long long int b10;
11     int idx;
12 
13     if (x == 0) {
14         return 0;
15     } else if (x < 10) {
16         return 1;
17     }
18 
19     b10 = 1;
20     idx = 0;
21     while (b10 * 10 <= x) {
22         b10 *= 10;
23         ++idx;
24     }
25     /*
26     printf("b10 = %lld\n", b10);
27     printf("idx = %d\n", idx);
28     */
29     if (x / b10 > 1) {
30         return (x / b10) * sum[idx] + b10 + solve(x % b10);
31     } else {
32         return sum[idx] + (x % b10 + 1) + solve(x % b10);
33     }
34 }
35 
36 int main()
37 {
38     int i;
39     int x, y;
40     long long int b10;
41 
42     sum[0] = 0;
43     sum[1] = 1;
44     b10 = 1;
45     for (i = 2; i <= 10; ++i) {
46         b10 *= 10;
47         sum[i] = 10 * sum[i - 1] + b10;
48     }
49 
50     /*
51     for (i = 0; i <= 10; ++i) {
52         printf("sum[%d] = %lld\n", i, sum[i]);
53     }
54     */
55 
56     while (scanf("%d%d", &x, &y) == 2) {
57         // the problem should‘ve told me what to do if x > y, it‘s unfair.
58         if (x > y) {
59             i = x;
60             x = y;
61             y = i;
62         }
63 
64         if (x == 0) {
65             printf("%lld\n", solve(y));
66         } else {
67             printf("%lld\n", solve(y) - solve(x - 1));
68         }
69     }
70 
71     return 0;
72 }
剑指Offer - 九度1373 - 整数中1出现的次数(从1到n整数中1出现的次数)

剑指Offer - 九度1373 - 整数中1出现的次数(从1到n整数中1出现的次数)

上一篇:[AWS vs Azure] 云计算里AWS和Azure的探究(5) ——EC2和Azure VM磁盘性能分析


下一篇:Cassandra1.2文档学习(17)—— CQL数据模型(上)