统计数字问题

POJ1016

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

  给定表示书的总页码的 10 进制整数 n  (1≤n≤109)  。计算书的全部页码中分别用到多少次数字0,1,2,…,9。 

根据n的范围,考虑使用unsigned long 类型


(1)统计0的个数

例:108

个位上出现0的次数为108/10=10

十位上出现0的次数为108-(10*10)+1=9

共19次

例:118

个位上出现0的次数为118/10=11

十位上出现0的次数为10

共21次

例:208

个位上出现0的次数为208/10=20

十位上出现0的次数为10+208-(20*10)+1=19

共39次

伪代码如下


cur_num=n;
mult=1;
q=0;
r=0;
while(cur_num)
{
    q=cur_num/10;
    r=cur_num%10;
    if(q>0 && r>0)
       cnt+=q*mult;
    else if(q>0 && r==0)
       cnt+=n-cur_num*mult+1;
    if(q>1 && r==0)
       cnt+=(q-1)*mult;
   mult*=10;
   cur_num/=10;
}

例:108

mult=1      q=10  r=8  cnt+=10

mult=10    q=1    r=0  cnt+=108-10*10+1=9

mult=100  q=0   r=1  cnt+=0;

cnt=19

例:118

mult=1      q=11  r=8  cnt+=11

mult=10    q=1    r=1  cnt+=q*mult=10

mult=100  q=0   r=1  cnt+=0;

cnt=21

例:208

mult=1      q=20  r=8  cnt+=20

mult=10    q=2    r=0  cnt+=(208-20*10+1)+(2-1)*10=19

mult=100  q=0   r=2  cnt+=0;

cnt=39

(2)统计1的次数

例:108

个位上1的次数为10+1

十位上1的次数为10

百位上1的次数为9

共30次

mult=1      q=10  r=8  cnt+=10*1+1=11

mult=10    q=1   r=0  cnt+=1*10=10

mult=100  q=0  r=1  cnt+=108-1*100+1=9

cnt=30

例:118

个位上1的次数为11+1=12

十位上1的次数为10+(118-110+1)=19

百位上1的次数为118-100+1=19

共50次

mult=1      q=11  r=8  cnt+=11*1+1=12

mult=10    q=1   r=1  cnt+=1*10+118-110+1=19

mult=100  q=0  r=1  cnt+=118-1*100+1=19

cnt=50

 while(cur_num)
	{
		quotient=cur_num/10;
		remainder=cur_num%10;
		
		cnt+=quotient*mult;
		if(remainder>1)
			cnt+=mult;
		else if(remainder==1)
			cnt+=n-cur_num*mult+1;
		mult*=10;
		cur_num/=10;
	}

(3)统计其他数的次数

和1类似



最终代码如下:

#include<stdio.h>
void Count(unsigned long n);
int main()
{
	unsigned long  n;
	scanf("%ld",&n);
	Count(n);

	return 0;
}
void Count(unsigned long n)
{
	unsigned long cur_num=n;
	int cnt[10]={0};
	int mult=1;
	unsigned long quotient=0;
	unsigned long remainder=0;
	int temp=0;
	int i;
	
	while(cur_num)
	{
		quotient=cur_num/10;
		remainder=cur_num%10;
		if(quotient>0 && remainder>0)
		   cnt[0]+=quotient*mult;
		else if(quotient>0 && remainder==0)
			cnt[0]+=n-cur_num*mult+1;
		if(quotient>1 && remainder==0)
			cnt[0]+=(quotient-1)*mult;

		for(i=1;i<=9;i++)
		{
			cnt[i]+=quotient*mult;
			if(remainder>i)
				cnt[i]+=mult;
			else if(remainder==i)
				cnt[i]+=n-cur_num*mult+1;
		}
		mult*=10;
		cur_num/=10;
	}
	for(i=0;i<=9;i++)
		printf("%d\n",cnt[i]);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值