• 数字统计问题


    问题描述:一本书的页码从自然数1开始顺序编码直到自然数n。书的页码按照通常的习惯编排,每个页码都不含多余的前导数字0。例如第6页用6表示而不是06或006。

    数字统计问题要求对给定书的总页码,计算出书的全部页码中分别用到多少次数字0,1,2,3,.....9。

    对于这样一个数字统计,换而言之就是从1到num(num>1且num属于正整数)这个数列中出现0,1,2,3,.....9数字的次数分别是多少?

    设f[n]为n位数中各个数字出现的次数,以2345为例,2345可以分为000-999,0至9出现的次数都为10f[n-1]+10n-1;1000-1999,0,2,3,4,5,6,7,8,9出现的次数都是10f[n-1]+10n-1,而1出现此时则为f[3]加上10的n-1次方即10的3次方,如f[3]为000~999中0~9中每一个数字出现的次数,则有,f[1]=1,f[n]=10f[n-1]+10n-1,故f[n]=n10n-1

    可令long f[10]={0,1,20,300,4000,50000,600000,7000000,80000000,900000000};

    3512为例

    (1)对千位上的数字a[1]=3进行处理:

    S1:000~999,1000~1999,2000~2999中(不包括千位)包含的各数字的个数为count[j]+=3*f[3],f[3]为000~999中所含的各位数字的个数

    S2:千位上的数字的个数:1、2各有103

    S3:3的个数为512+1个(从3000~3512)

    (2)用同样的方法处理其余各位数5、1、2

    (3)最后减去0个数

     //创建静态数组f表示各数字在n位数中出现的次数
    static long [] f={0,1,20,300,4000,50000,600000,7000000,80000000,900000000};
    //创建静态数组count用来存储各数字出现的次数
    static long [] count={0,0,0,0,0,0,0,0,0,0};
    public static void page(int a[]) {//用数组a来表示各位数的数字
            int n = a.length;
            for(int i=1;i<=n;i++) {//从最高位开始计算到最低位
                for (int j = 0; j < 10; j++) count[j] += a[i - 1] * f[n - i];//0到9的高位
                for (int j = 0; j < a[i - 1]; j++) count[j] += Math.pow(10, n - i);
                for (int j = i+1; j <= n; j++) count[a[i-1]] += (a[j - 1] * Math.pow(10, n - j));
                count[a[i-1]]++;
            }
        }

    用数组a表示个位数的数字,从最高位开始计算0到9出现的次数至计算到最低位,

    for (int j = 0; j < 10; j++) count[j] += a[i - 1] * f[n - i];即是000~999,1000~1999,2000~2999...的计算形式。
    for (int j = 0; j < a[i - 1]; j++) count[j] += Math.pow(10, n - i);即是i-1数位上的数字n由1到n-1各出现Math.pow(10, n - i)的计算形式。
    for (int j = i+1; j <= n; j++) count[a[i-1]] += (a[j - 1] * Math.pow(10, n - j));这里使用了递归说明比较复杂,用简明的说法就是以3512为例3的个数为512个(从3000~3512)而
    count[a[i-1]]++;3的个数为512+1个,再从512返回for (int j = 0; j < 10; j++) count[j] += a[i - 1] * f[n - i];开始计算。

    示例:
    package jihe;
    
    import java.util.Scanner;
    
    /**
     * author Gsan
     */
    public class Page {
        //创建静态数组f表示各数字在n位数中出现的次数
        static long [] f={0,1,20,300,4000,50000,600000,7000000,80000000,900000000};
        //创建静态数组count用来存储各数字出现的次数
        static long [] count={0,0,0,0,0,0,0,0,0,0};
    
         public static void page(int a[]) {//用数组a来表示各位数的数字
            int n = a.length;
            for(int i=1;i<=n;i++) {//从最高位开始计算到最低位
                for (int j = 0; j < 10; j++) count[j] += a[i - 1] * f[n - i];//0到9的高位
                for (int j = 0; j < a[i - 1]; j++) count[j] += Math.pow(10, n - i);
                for (int j = i+1; j <= n; j++) count[a[i-1]] += (a[j - 1] * Math.pow(10, n - j));
                count[a[i-1]]++;
            }
        }
    
            public static void main (String[]args){
             int [] a={3,5,1,2};
             page(a);
             for (int i = 0; i <a.length; i++) count[0] -= Math.pow(10, i);
             for (int i = 0; i < count.length; i++)
                 System.out.println("数字" + i + "出现次数为:" + count[i]);
        }
    }
    for (int i = 0; i <a.length; i++) count[0] -= Math.pow(10, i);减去如000-999这样形式与由1出现编码而多出来计算的0的次数的计算形式。
    运行结果:
     
  • 相关阅读:
    oracle学习之数据库数据保存成文件
    秦时明月这部烂电视
    Oracle学习之buffer cache(copy过来的文本,待补充笔记)
    Oracle学习之shared pool及sga的大小的设置
    Oracle学习之sql共享以及4031解决方法
    Oracle学习之内存块组成结构及4031错误分析
    树形逻辑套路总结
    HashMap并发分析
    JVM常用指标查询
    读Lock-Free论文实践
  • 原文地址:https://www.cnblogs.com/Gsan/p/10493564.html
Copyright © 2020-2023  润新知