统计数字问题(算法设计与分析 王晓东)C++

问题描述:输入页码n后计算数字0-9出现的次数,对于类似于06的页码,不计算0,只计算6。


采取递归的方式:

1.对于类似于06的页码,先计算上0,等后续再删掉。

2.  0-9  页,0-9各出现1次;

   0-99  页,0-9各出现2*(10^1)次;

   0-999页,0-9各出现3*(10^2)次……

(对于一个三位数□□□,以数字1出现的次数为例:

1位于百位时,0-9的可以出现在十位、个位,即10^2次;

1位于十位时,0-9的可以出现在百位、个位,即10^2次;

1位于个位时,0-9的可以出现在百位、十位,即10^2次;

所以各个数字出现的次数为:

位数*10^(位数-1)。)


一、找页数n的位数:int weishu=log10(n)+1;

二、对页数n进行区间划分+统计数字

1.

以2127为例,考虑2127区间数。

0000-0999   √

1000-1999  √

由于2000-2999超过2127,故不考虑该区间。

以上每个区间除千位数外0-9各出现300次,

区间数为n/10^(weishu-1)取整,

即2127/10^3=2,另外区间数与该数2127的最高位一致均为2,定义:

int zuigaowei=n/(int)pow(10.0,weishu-1);

除最高的千位数外,0-9总共出现2*(4-1)*10^(4-2)次,即 区间数*(位数-1)*10^(位数-2)。

a[i]+=zuigaowei*(weishu-1)*(int)pow(10.0,weishu-2);

最高位千位出现次数,0:1000次;1:1000次。

for (int i=0;i<zuigaowei;i++)
	{
		a[i]+=(int)pow(10.0,weishu-1);  
	}

2.

2127/10^3取余为127,故以下考虑127区间数。

000-099   √

因为100-199超过127,故不考虑该区间 。 

以上每个区间除百位数外0-9各出现20次,

区间数为127/10^2=1,与该数127最高位一致。

除最高的百位数外,0-9总共出现1*(3-1)*10^(3-2)次,即 区间数*(位数-1)*10^(位数-2)。

最高位百位出现次数:0:100次。

对于千位数的2,出现127+1=128次。

int yu=n%int(pow(10.0,weishu-1)); 
a[zuigaowei]+=1+yu;

3.

127/10^2取余为27,故以下考虑27区间数。

00-09;√

10-19;√

以上每个区间除十位数外0-9各出现1次,

区间数为27/10^1=2,与该数27最高位一致。

除最高的十位数外,0-9总共出现2*(2-1)*10^(2-2)次,即 区间数*(位数-1)*10^(位数-2)。

最高位十位出现次数:0:10次;1:10次。

对于百位数上的1,出现27+1=28次。

4.

20-27单独考虑。

最高位0-7上的数字出现10^(位数-1)次,即各一次。

对于十位数上的2,27/10^1余数为7,出现7+1=8次。

三、考虑余数为0的情况

如3000

if(yu==0) //如3000 
	{
		a[0]+=weishu-1;
		a[zuigaowei]++;
		return;
	}

 

四、减去多余的0

9a8421b26b404e60b00d76326a6b11a5.png

应减去0的个数为10^0+10^1+10^2……10^(位数-1)。

五、代码

#include <iostream>
#include<cstdio>
#include<cmath>
using namespace std;
int a[10];
void solve(int n)
{
	int weishu=log10(n)+1; 
	int zuigaowei=n/((int)(pow(10.0,weishu-1))); 
	for (int i=0;i<10;i++)
	{
		a[i]+=zuigaowei*(weishu-1)*(int)pow(10.0,weishu-2);
	}
	for (int i=0;i<zuigaowei;i++)
	{
		a[i]+=(int)pow(10.0,weishu-1);  
	}
	int yu=n%int(pow(10.0,weishu-1)); 
	int weishut=log10(yu)+1;
	if(yu==0) //如3000 
	{
		a[0]+=weishu-1;
		a[zuigaowei]++;
		return;
	}
	a[zuigaowei]+=1+yu;
	return solve(yu);	
}
int main()
{
	int n;
	while (cin>>n)
	{ 
		fill (a,a+10,0);
		int weishu=log10(n)+1;
		solve(n);
		for (int i=0;i<weishu;i++) 
		{
			a[0]-=(int)pow(10.0,i);
		}
		for(int i=0;i<10;i++)
		{
			cout<<i<<"出现次数为:"<<a[i]<<endl;
		}
	}
}

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值