• UVa 1640 (计数) The Counting Problem


    题意:

    统计[a, b]或[b, a]中0~9这些数字各出现多少次。

    分析:

    这道题可以和UVa 11361比较来看。

    同样是利用这样一个“模板”,进行区间的分块,加速运算。

    因为这里没有前导0,所以分块的时候要多分几种情况。

    以2345为例,这是一个四位数,首先要计算一下所有的一位数、两位数以及三位数各个数字出现的个数。

    对应的模板分别为n,n*,n**,其中n代表非零数字,*代表任意数字。

    考虑这样一个长为l的模板****(l个*),这样的数共10l个,而且各个数字都是等频率出现,所以每个数字出现的次数为l * 10l-1

    统计完三位数一下的数字之后,就开始统计四位数字:1***,20**,21**,22**,230*,231*,232*,233*,2340,2341,2342,2343,2344,2345

    在统计每个模板时,分这样两块计算:

    • **中该数字出现的次数
    • 前面该数出现的次数,比如22**,前面两个2会重复102
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 int pow10[10], cnt[10];
     7 
     8 int f(int d, int n)
     9 {
    10     char s[15];
    11     sprintf(s, "%d", n);
    12     int len = strlen(s);
    13     int ans = 0;
    14 
    15     for(int i = 1; i < len; i++)
    16     {
    17         if(i == 1) { ans++; continue; }
    18         ans += 9 * cnt[i - 1];
    19         if(d > 0) ans += pow10[i - 1];
    20     }
    21 
    22     int pre[10];
    23     for(int i = 0; i < len; i++)
    24     {
    25         pre[i] = (int)(s[i] - '0' == d);
    26         if(i) pre[i] += pre[i - 1];
    27     }
    28 
    29     for(int i = 0; i < len; i++)
    30     {
    31         int maxd = s[i] - '0' - 1;
    32         int mind = 0;
    33         if(i == 0 && len > 1) mind = 1;
    34         for(int digit = mind; digit <= maxd; digit++)
    35         {
    36             ans += cnt[len - i - 1];
    37             if(i) ans += pre[i - 1] * pow10[len - i - 1];
    38             if(digit == d) ans += pow10[len - i - 1];
    39         }
    40     }
    41     return ans;
    42 }
    43 
    44 int main()
    45 {
    46     //freopen("in.txt", "r", stdin);
    47 
    48     pow10[0] = 1;
    49     for(int i = 1; i <= 8; i++)
    50     {
    51         pow10[i] = pow10[i - 1] * 10;
    52         cnt[i] = pow10[i - 1] * i;
    53     }
    54 
    55     int a, b;
    56     while(scanf("%d%d", &a, &b) == 2 && a && b)
    57     {
    58         if(a > b) swap(a, b);
    59         for(int d = 0; d <= 9; d++)
    60         {
    61             if(d) printf(" ");
    62             printf("%d", f(d, b+1) - f(d, a));
    63         }
    64         printf("
    ");
    65     }
    66 
    67     return 0;
    68 }
    代码君
  • 相关阅读:
    Microsoft Dynamics CRM 常用JS语法(已转成vs2017语法提示)
    IIS7如何实现访问HTTP跳转到HTTPS访问
    C#调用PB写的com组件dll
    C# winform程序免安装.net framework在XP/win7/win10环境运行!
    文件上传漏洞
    OWASP TOP 10
    sql
    ASCII码查看
    sql注入--mysql
    sql注入--access
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4318926.html
Copyright © 2020-2023  润新知