数字统计之统计页码

问题描述:

一本书的页码从自然数1开始计数,直到自然数n。书的页码按照通常的习惯编排,每个页码都不包含多余的前导数字0。例如,第6页用数字6表示,而不是06或006等。数字计数问题要求对给定书的总页码n,计算出书的全部页码中分别用到多少次数字0,1,2,...,9。

参考代码:

方法一 

暴力求解。无论页码是多少都是从1...n,所以我们可以从1到n进行遍历并对每个数进行分解即可得到结果

#include<stdio.h>
int main(){
	int n,i,temp;

	//声明并且初始化数组
	int count[10]={0};
	printf("请输入页码:");
	scanf("%d",&n);

	//从1到n遍历数字,并分解将对应数字加1
	for(i=1;i<=n;i++){
		for(temp=i;temp>0;temp/=10){
			count[temp%10]++;
		}
	}

	//遍历输出
	for(i=0;i<10;i++)
		printf("%d\n",count[i]);
	return 1;
}

方法二

    考虑一个数字12345,在个数上,数字出现的频率是1次,即0到9不断循环出现;而在10位数字上(如果十位上没有数字就补0,要求从0到12345这些数字的位数都和最大的数相同,这里就都是5位),每个数字是连续出现10次后再出现另一个数字;百位数字上依此类推……

    基于这个思路,如果我们能计算出0到9这10个数字在每一位上出现的次数,对它们进行求和,即可计算出这10个数字出现的次数。

    考虑**X**,在第3位上统计相关数字出现的次数。一般地,数字出现的次数与X的大小有直接的有关系。

1)如果数字比X大,则它在这一位上出现的次数与前面的数字和该数字所在的位置有关。例如,12345中,数字4在第3位出现的次数为:

12*100=1200

    (2)如果数字等于X,则它在这一位上出现的次数与前面的数字、后面的数字和该数字所在的位置有关。例如,12345中,数字3在第3位上出现的次数为:

12*100+45+1=1246

    (3)如果数字小于X,则它在这一位上出现的次数与前面的数字和该数字所在的位置有关。例如,12345中,数字2在百位上出现的次数为

12+1)*100=1300

 

#include<stdio.h>
#include<math.h>
int main(){
	int n,i,j,highter,lower,temp;
	int ws;
	//声明并且初始化数组
	int count[10]={0};
	printf("请输入页码:");
	scanf("%d",&n);

	//计算n的位数
	ws=log10((double)n)+1;

	//依次计算第i(i小于ws)位0到9出现的次数
	for(i=1;i<=ws;i++){

		//记录第i位之上的高位
		highter=n/(int)pow((double)10,i);
		
		//记录第i位之下的低位
		lower=n%(int)pow((double)10,i-1);

		//记录第i位
		temp=(n/(int)pow((double)10,i-1))%10;

		//记录小于第i位的数字在i位出现的次数
		for(j=0;j<temp;j++){
			count[j]+=(highter+1)*pow((double)10,i-1);
		}

		//记录第i位上的数字在第i位出现的次数
		count[temp]+=highter*pow((double)10,i-1)+lower+1;
		
		//记录大于第i位的数字在第i位出现的次数
		for(j=temp+1;j<10;j++){
			count[j]+=highter*pow((double)10,i-1);
		}
	}

	//剔除多余的0
	for(i=0;i<ws;i++)  
        count[0]-=(int)pow((double)10,i);
	
	
	//遍历输出
	for(i=0;i<10;i++)
		printf("%d\n",count[i]);
	return 1;
}

方法三

    给定一个n位数字number,我们首先看一下从0到最大的n位数字,如果位数不够,在前面填0,这样一共有10^n个数字,其中包含数字的个数是n*10^n,其中包含这10个数字是相同的,都为n*10^{n-1}位。

   能否根据这一思路,从高位到低位依次处理?得到最终的位数?可以首先把最高位的数字单独处理,然后再处理其他的n-1位,最后把那些多余的0全部去掉就可以了。

 

#include<stdio.h>
#include<math.h>
int main(){
	int n,i,j,k,highter,lower,temp;
	int ws;
	//声明并且初始化数组
	int count[10]={0};
	printf("请输入页码:");
	scanf("%d",&n);

	//计算n的位数-1
	ws=log10((double)n);
	
	//将n分解,依次记录最高位数字
	temp=n;	
	for(i=0;i<=ws;i++){
		//取得最高位数字
		highter=temp/pow((double)10,ws-i);
		//取得低位数字
		lower=temp%(int)pow((double)10,ws-i);

		//记录最高位数字在最高位出现的次数
		count[highter]+=lower+1;

		//依次记录从0到最高位数字highter的数字在最高位出现的次数以及从0到ws-i位最大数0到9出现的次数
		for(j=0;j<highter;j++){
			count[j]+=pow((double)10,ws-i);

			//0到ws-i位最大数0到9出现的次数
			for(k=0;k<10;k++){
				count[k]+=(ws-i)*pow((double)10,ws-i-1);  
			}
		}
		temp=lower;
	}
	

	//剔除多余的0
	for(i=0;i<=ws;i++)  
        count[0]-=(int)pow((double)10,i);
	//遍历输出
	for(i=0;i<10;i++)
		printf("%d-->%d\n\n1",i,count[i]);
	return 1;

}


  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值