• 11 统计数字问题


    最近学习算法设计与分析,老师推荐王晓东的计算机算法设计与分析,感觉真的很不错,但是第一到算法实现题就给难住了,题目如下(后来发现编程之美上也有这个题目,只是让求1出现的次数):

    一本书的页码从自然数1开始顺序编码直到自然数n。每个页码不包含多余的前导数字0.给定书的总页码,计算出书的全部页码中分别用到多少次数字0,1,2,。。。9.
    一下子能想到的笨方法就是遍历1到n之间的每个数字,统计每个页码数中每个数字出现的次数,这样非常慢。

    代码如下:

    #include <stdio.h>
    #include <time.h>

    int countInteger(int m)
    {
    int num = 0;
    while(m != 0) {
    num += (m % 10 == 1) ? 1 :0;
    m /= 10;
    }
    return num;
    }
    int main()
    {
    int n,i;
    int count = 0;
    scanf("%d", &n);
    double start = (double)clock();
    for (i = 1; i <= n; i++) {
    count += countInteger(i);
    }
    double finish = (double)clock();
    printf("%d\ntime = %.20fms\n", count, (finish - start)/1000);
    return 0;
    }

    参考编程之美的方法后可改进下:

    假设给定总页码为N=abcde,当前处理到c,即统计百位上每个数字出现次数,则具有如下规律:
    如果要统计百位上数字i出现的次数(i=0,1,2,3,...9),其实它受到三个因素的影响:百位上的数字(curnum),百位以下的数字(lownum),百位以上的数字(hignum).
    如果百位上数字c>i则:sum[i]+=(hignum+1)*fact,其中sum[i]表示百位上出现i的次数,hignum=ab,fact表示当前处理到的位的基数,百位时fact=100,十位时fact=10,个位时fact=1;
    如果百位上数字c=i则:sum[i]+=hignum*fact+lownum+1,此处hignum=ab,lownum=de
    如果百位上数字c<i则:sum[i]+=hignum*fact; 此处hignum=ab
    另外,
    000 
    001
    ....(9)
    009
    010
    ....(90)
    099
    100
    ....(900)
    999
    需要去掉这写开头是0的数字中多余的0,当n的数字长度为len时,多余的0的个数为,
    len=1时为0+1个
    len=2时为1*9*10^0+2个
    len=3时为9*10^1+2*9*10^0+3个
    ...
    len=k时为9+99+999+...+99..99(k个9)+k个
     

    因此代码如下:

    #include <stdio.h>
    #include <math.h>
    #include <time.h>

    /**int power(int x, int y)
    {
    int i;
    int s = 1;
    for (i = 0; i < y; i++) {
    s *= x;
    }
    return s;
    }**/
    int sum(int n)
    {
    int sum[10] = {0};
    int hignum = 0;
    int lownum = 0;
    int curnum = 0;
    int fact = 1;
    int i;
    int len = 0, zero = 0;

    while (n / fact != 0) {
    lownum = n - (n / fact) * fact;
    curnum = (n / fact) % 10;
    hignum = n / (fact * 10);
    for (i = 0; i < 10; i++) {
    if (curnum > i) {
    sum[i] += (hignum + 1) * fact;
    }
    else if (curnum == i) {
    sum[i] += hignum * fact + lownum + 1;
    }
    else {
    sum[i] += hignum * fact;
    }
    }
    fact *= 10;
    len++;
    }
    for (i = 0; i < len; i++) {
    zero += (len - i - 1) * 9 * pow(10*1.0, i*1.0) * 1.0;
    }
    zero += len;
    sum[0] -= zero;
    for (i = 0; i < 10; i++) {
    printf("%d : %d\n", i, sum[i]);
    }
    }

    int main()
    {
    int n;
    while(scanf("%d", &n) != EOF) {
    sum(n);
    }
    return 0;
    }

    注:以上内容出于学习目的,借鉴他人之处,未经允许,经请谅解。

  • 相关阅读:
    Failed to load module "canberra-gtk-module"
    [Ubuntu18]桌面美化-仿MAC主题
    [Ubuntu]18自定义切换输入法的快捷键
    2016-2017-1 《信息安全系统设计基础》 学生博客及Git@OSC 链接
    2015-2016-2 《Java程序设计》 游戏化
    2015-2016-2 《Java程序设计》项目小组博客
    博客引用书单
    2015-2016-2 《网络攻防实践》 学生博客
    2015-2016-2 《网络攻击与防范》 学生博客
    《网络攻防技术与实践》学习指导
  • 原文地址:https://www.cnblogs.com/taotao315/p/2950764.html
Copyright © 2020-2023  润新知