统计数字问题
习题1-1 统计数字问题。给定一本书,其中包含n页,计算出书的全部页码中用到了多少个数字0…9。
样例输入:
11
样例输出:
1
4
1
1
1
1
1
1
1
1
传统方法是从1循环到12345,然后用取模运算依次提取出每一位数字,统计每一个数字出现的次数,这样对于小的数字来说还可以,当数字变得很大很大时,此方法显然太过于浪费时间。
这里给出一种思路,依次统计每一位上出现的数字的个数。
因为这里是从1–12345,1就只有自己1,而不是000001,但是为了统计方便,这里先按照00000–12345来计算,最后再减去多统计的数字0.
以中间数字3为列,3的位置是百位,先看百位这个地方会出现几个0,可以发现00000 - 12099最小是00000,最大是12099,那么这是出现了多少个0呢,百位的左边是0-12,右边是0-99那么0这个数字在百位出现的次数就是13(百位左边)* 100(右边从0数到99)个。同样1的时候最小是00100,最大12199,数字1出现的次数就是13 * 100,依次类推。但是当到了3的时候就不是了,3的时候最小是00300,最大12345,而不是12399了,这样就分成了00300-11399 再加上11300-11345这样3出现的次数就是12*100+45+1,
为什么要加1,因为是从0-45,后面代码中解释。3之后就是4 5 6 7 8 9了,这些数字以4为例,最小00400,最大11499,一共12*100个数字,所以可以总结一下获取每一位上出现的数字的次数的计算方法。
先统计一下给出的数字一共几位,依次取出每一位,记作middle,middle的左边记作high,右边记作low,那么0到middle - 1出现的次数就是 (high+1)*pow(10,i),
middle出现的次数就是high * pow(10,i)+ low + 1;
middle+1到9出现的次数就是high * pow(10,i)
最后再解决0的问题,各位上从0到5,多算了一个0,十位上从00到09多算了10个,百位从000到099多算了100个以此类推减去多算的0的个数。
代码如下
#include<stdio.h>
#include<math.h>
int main(){
int i,j,count;
int high,low,middle;
int a[10] = {0};//初始化数组,用来统计0-9的个数
int number = 11;//要统计的数字,可以是任意大于0的数
count = (int)log10(number)+1;//统计一共几位
for(i = 1;i <= count;i++){
high = number / pow(10,i);//取出middle的左边的数
low = number % (int)pow(10,i-1);//取出middle的右边的数
middle = number / (int)pow(10,i-1) % 10 ;//取middle
for(j = 0;j < middle; j++)
a[j] += (high+1) * (int)pow(10,i-1);//计算0到middle-1
a[j] += high * (int)pow(10,i-1) + low + 1;//计算middle
for(j = middle+1;j < 10;j++)
a[j] += high * (int)pow(10,i-1);//计算middle+1到9
}
for(i = 0;i < count;i++)
a[0] -= (int)pow(10,i);//剔除多余的0
for(i = 0;i < 10;i++)
printf("%d\t",a[i]);
}
运行结果如下