统计数字问题。给定一本书,其中包含n页,计算出书的全部页码中用到了多少个数字0…9。
样例输入:
11
样例输出:
1
4
1
1
1
1
1
1
1
1
解法1:
暴力解决,统计0~9出现的次数,从1遍历到给出数字,对于每一个数字的每一位进行判断,在相应的数字数量上进行加1。
#include<stdio.h>
int main()
{
int n;
int i,count;
int a[10]={0};
while(scanf("%d",&n)){
for(i=1;i<=n;i++){
count=i;
while(count){
a[count%10]++;
count=count/10;
}
}
for(int i=0;i<10;i++)
printf("%d\n",a[i]);
}
return 0;
}
解法2:
在数字递增过程中,认为进行位数补全,如1~99则变成00~99。而此时,每个数字出现的次数是相同的。
每个数字出现的次数为:f(n)=n*10^n-1(n为数字的位数);
因此利用上述公式进行求解。此时需要对给定数进行分解(例如2156)。
从第一位开始,分成三部分:
长度为4,所以能够选出000~999的两组,实际上是000~999和1000~1999根据公式可以求得此部分的数量;
最高位出现的次数,2出现的次数为2000~2156即为157次;
在最高位上出现但是小于最高位的数字出现的次数即0、1出现的次数,0为000~1000最高位上为0的次数为 pow(10,4-1),1为1000~1999同样是pow(10,4-1)。
在最高位分析完成之后,指针向后移动最高位变成1,长度为3按照上述步骤进行。
全部计算完成之后,需要减去多余的0,当数字为1时多余1个0,2位时多余1+10个0,3位时多余1+10+100个0;
#include<stdio.h>
#include<math.h>
#include<string.h>
int a[10];
int main()
{
int n;
while(~scanf("%d",&n)){
memset(a,0,sizeof(a));
int len = log10(n);
int temp = n;
int count;
int high=0;
int remain=0;
for(int i=0;i<=len;i++)
{
high=temp/pow(10,len-i);//获取最高位
remain=temp-high*pow(10,len-i);//获取剩余位数的大小
a[high]+=remain+1;//最高位出现的次数因从0开始所以还需要加 1
for(int z=0;z<high;z++){
a[z]+=pow(10,len-i); //小于最高位数字出现的次数,就是10的len-i次方。
}
for(int j=0;j<10;j++){
a[j]+=high*(len-i)*pow(10,len-i-1);
//类似00~99之间数字出现次数相同为(len)*(pow(10,len-1))
//因为这里的实际长度为len-i;所以上式中len为len-i
//每个类似区间出现的次数为此时数字的最高位;
}
temp=remain;
//计算完成最高位之后,再次计算剩余部分,
//此时把剩余数字当作初始数据计算。直到数字的长度为0
}
for(int i=0;i<=len;i++){
a[0]-=pow(10,i);
}
for(int j=0;j<10;j++){
printf("%d\n",a[j]);
}
}
return 0;
}