zoukankan      html  css  js  c++  java
  • 剑指Offer

    剑指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)哦。
     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
    ", b10);
    27     printf("idx = %d
    ", 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
    ", 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
    ", solve(y));
    66         } else {
    67             printf("%lld
    ", solve(y) - solve(x - 1));
    68         }
    69     }
    70 
    71     return 0;
    72 }
  • 相关阅读:
    Arcmap软件报错:This application cannot run under a virtual machine arcmapr, 但是你并没有使用虚拟机
    Sql server 2008 作业失败通知邮件配置
    能drag和resize的DIV,目的是做一个类似于数据库视图设计器
    Type.GetType()与System.Web.Compilation.BuildManager.GetType()
    让你的实体字段和页面上的控件映射,自动绑定 ObjectBinding1.0
    利用Log Explor来恢复误用delete 、update了的数据
    破解版果冻手机动画主题for WM5 & WM6
    封装一个图片轮换的web控件
    利用Lucene.net对附件做搜索
    关于TransactionScope分布式事务在Oracle下的运作
  • 原文地址:https://www.cnblogs.com/zhuli19901106/p/3538509.html
Copyright © 2011-2022 走看看