• UVa 1640


    链接:

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4515

    题意:

    给出整数a、b,统计a和b(包含a和b)之间的整数中,数字0,1,2,3,4,5,6,7,8,9分别出现了多少次。1≤a,b≤1e8。

    分析:

    解决这类题目的第一步一般都是:令f(n,d)表示0~n中数字d出现的次数,则所求的就是f(b,d)-f(a-1,d)。
    例如,要统计0~234中4的个数,可以分成几个区间:

    范围                    模板集
    0~9                    *
    10~99                **
    100~199            1**
    200~229            20*,21*,22*
    230~234            230,231,232,233,234

    上表中的“模板”指的是一些整数的集合,其中字符“*”表示“任意字符”。例如,1**表示以1开头的任意3位数。
    因为后两个数字完全任意,所以“个位和十位”中每个数字出现的次数是均等的。
    换句话说,在模板1**所对应的100个整数的200个“个位和十位”数字中,0~9各有20个。
    而这些数的百位总是1,因此得到:模板1**对应的100个整数包含数字0,2~9各20个,数字1有120个。
    这样,只需把0~n分成若干个区间,算出每个区间中各个模板所对应的整数包含每个数字各多少次,就能解决原问题了。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 
     4 const int UP = 10;
     5 int pow10[UP], amt[UP];
     6 
     7 int f(int n, int d) {
     8     int res = 0;
     9     char s[99];
    10     sprintf(s, "%d", n);
    11     int len = strlen(s);
    12 
    13     for(int i = 1; i < len; i++) {
    14         if(i == 1) res++;
    15         else {
    16             res += 9 * amt[i-1];
    17             if(d > 0) res += pow10[i-1];
    18         }
    19     }
    20 
    21     int pre = 0;
    22     for(int i = 0; i < len; i++) {
    23         int L = 0, R = s[i]-'0';
    24         if(i == 0 && len > 1) L = 1;
    25         for(int digit = L; digit < R; digit++) {
    26             res += amt[len-1-i] + pre * pow10[len-1-i];
    27             if(digit == d) res += pow10[len-1-i];
    28         }
    29         if(s[i]-'0' == d) pre++;
    30     }
    31     return res + pre;
    32 }
    33 
    34 int main() {
    35     pow10[0] = 1;
    36     for(int i = 1; i < UP; i++) {
    37         pow10[i] = pow10[i-1] * 10;
    38         amt[i] = pow10[i] * i / 10;
    39     }
    40     int a, b;
    41     while(scanf("%d%d", &a, &b) && a) {
    42         if(a > b) b += a, a = b-a, b -= a;
    43         printf("%d", f(b,0) - f(a-1,0));
    44         for(int i = 1; i < 10; i++) printf(" %d", f(b,i) - f(a-1,i));
    45         printf("
    ");
    46     }
    47     return 0;
    48 }
  • 相关阅读:
    [充电]多线程无锁编程--原子计数操作:__sync_fetch_and_add等12个操作
    [转]架构、框架、模式、模块、组件、插件、控件、中间件的含义
    [网络]网络爬虫
    PHP时间戳和日期转换
    两个input之间有空隙,处理方法
    去除输入框原始效果【原创】
    php做图片上传功能
    PHP获取随机数的函数rand()和mt_rand()
    PHP简单的图片上传
    基于layui的表格异步删除,ajax的简单运用
  • 原文地址:https://www.cnblogs.com/hkxy125/p/9631697.html
Copyright © 2020-2023  润新知