/**
* 问题:一本书的页码是从自然数1开始编码到n的。每个页码没有前导0,即第6页编码为6,而不是<br>
* 06,或者006.数字计数问题的要求是对给定书的总页码n,计算出书的全部页码中分别用刀的多少次<br>
* 0,1,……9.。1<=n<=10^9。
* 思路:对于一个数字t(0<=t<=9),分别考虑个位、十位……到n的最高位,这些位为t的数的个数,再分<br>
* 别加起来,就是所有页码中t的个数了
* <br>假定所有n>=1
* 问题:一本书的页码是从自然数1开始编码到n的。每个页码没有前导0,即第6页编码为6,而不是<br>
* 06,或者006.数字计数问题的要求是对给定书的总页码n,计算出书的全部页码中分别用刀的多少次<br>
* 0,1,……9.。1<=n<=10^9。
* 思路:对于一个数字t(0<=t<=9),分别考虑个位、十位……到n的最高位,这些位为t的数的个数,再分<br>
* 别加起来,就是所有页码中t的个数了
* <br>假定所有n>=1
* */
class numberCount{
private int n;
private int length;
private int[]result;
private static void confirm(int n,int[]result){//用于验证的方法,挨个计算每个整数各位上的数
while(n>0){
result[n%10]++;
n/=10;
}
}
public static void test(){//测试函数
int[]n={9,23,301,3423,34830,1000000,83049839};
for(int j:n){
numberCount nc=new numberCount(j);
int[]result=nc.getCount();
System.out.println("n="+j);
for(int t=0;t<10;t++){
System.out.println("digit="+t+" number="+result[t]);
}
int[]con=new int[10];
for(int k=1;k<=j;k++)
confirm(k,con);
for(int k=0;k<10;k++)
if(con[k]!=result[k]){
System.out.println("Error!");
for(int t:con)
System.out.println(t);
break;
}
}
}
public numberCount(int n){
this.n=n;
length=lengthOf();
}
/**获取所有页码中0-9每个数字的个数*/
public int[]getCount(){
if(result==null){
result = new int[10];
result[0] = getZeroCount();
for (int j = 1; j < 10; j++)
result[j] = getCount(j);
}
return Arrays.copyOf(result, result.length);
}
private int getZeroCount(){//计算0的个数,没有前导0,所以这个要单独计算
int pos=1,tk=10,zeroNumber=0;
while(pos<length){//0不能在最高位
zeroNumber+=(n/tk-1)*(tk/10);//没有前导0,所以要减1,后pos-1位构成数的个数是tk/10
if(pos>1){
// 考虑pos-1位
int na = n % tk;
int second = na * 10 / tk;//pos-1为的数字
if(second==0){//pos-1为0,则>n/tk*tk的数中符合的个数是na+1个
zeroNumber+=na+1;
}else{//若该位不为0,则符合的个数就是pos-1位的所有组合数,即tk/10
zeroNumber+=tk/10;
}
}else{
zeroNumber+=(n<10?0:1);
}
pos++;
tk*=10;
}
return zeroNumber;
}
private int getCount(int k){//计算1-9的个数
int pos=1,tk=10,number=0;
while(pos<=length){
number+=n/tk*(tk/10);
if(pos>1){
int na=n%tk;
int second=na*10/tk;
if(second==k){
number+=na-k*tk/10+1;
}else if(second>k){
number+=tk/10;
}
}else{
number+=n%10>=k?1:0;
}
pos++;
tk*=10;
}
return number;
}
private int lengthOf(){//计算n的十进制的长度
int r=0,t=1;
while(t<=n){
r++;
t*=10;
}
return r;
}
}