数字统计问题

问题描述:一本书的页码从自然数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个数1111

 //创建静态数组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的次数的计算形式。
运行结果:
 

猜你喜欢

转载自www.cnblogs.com/Gsan/p/10493564.html
今日推荐