《编程之美》--“1的数目”笔记

1的数目

给定一个是十进制正整数N,写下从1开始,到N的所有整数,然后数一下其中出现的所有“1”的个数。

例如:

N=2,写下1,2。这样只出现了1个“1”。

N=12,我们会写下1,2,3,4,5,6,7,8,9,10,11,12。这样,1的个数是5。

问题:写一个函数f(N),返回1到N之间出现的“1”的个数,比如f(12)=5;

解法:

仔细分析这个问题,给定了N,似乎就可以通过分析“小于N 的数在每一位上可能出现1的次数”之和来得到这个结果。对于一个特定的N,分析其中的规律。

先看1位数的情况

只要N>=1,那么f(N)都等于1。否则f(N)为0;

再看2 位数的情况。

如果N=13.那么从1到13的所有数字:1、2、3、4、5、6、7、8、9、10、11、12、13,个位和十位的数字都可能有1,我们可分开考虑。个位出现1的次数有两次:1和11,十位出现1的次数有4次:10、11、12和13,所以f(N)=2+4=6。要注意的是11这个数学在十位和个位都出现了1,但是11恰好分别被计算了一次,所以不用特殊处理。再考虑N= 23 的情况,它和N= 13 有点不同,十位出现1的次数为10次,从10到19,个位出现1的次数为1、11和21,所以f (N) =3+10= 13。通过对两位数进行分析,我们发现,个位数出现1的次数不仅和个位数字有关,还和十位数有关: 如果N的个位数大于等于I,则个位出现1的次数为十位数的数子加1; 如果N的个位数为0,则个位出现1的次数等于十位数的数字。而十位数上出现1的次数也类似: 如果十位数

字等于1,则十位数上出现1 的次数为个位数的数字加1; 如果十位数大于1,则十位数上出现1的次数为10。

f(13) =  一个位出现1的个数+ 十位出现1的个数=2+4=6:

f(23) =  一个位出现1的个数+ 十位出现1的个数=3+10=13;

f(33) = 一个位出现1的个数+ 十位出现1的个教=4+10 =14; …

f(93) = 一个位出现1的个数+  十位出现1的个数=10+10= 20;

接着分析3 位数。

如果N= 123:

个位出现1的个数为13:1,11,21,…,91,101,111,121

十位出现1的个数为20:10~19,110~119 百位出现1的个数为24: 100~123

f(123)= 个位出现1的个数+十位出现1的个数十百位出现1的次数=13+20+24=57;

同理我们可以再分析4 位数、5位数。

根据上面的尝试,下面我们推导一般情况下,从N得到f(N) 的计算方法。

假设N=abcde,这a、b、c、d、e分别是十进制数N的各个数位上的数字。如果要t计算百位上出现1的次数,它将会受到三个因素的影响:百位上的数字,百位以下(低位) 的数字,百位(更高位) 以上的数字。

如果百位上的数字为0,可知,百位上可能出现1的次数由更高位决定,比如12013,百位出现1的情况可能是100~199,1100~2199,2100~2199,…,11100~11199,共有1200个。也就是由更高位数字(12)决定,并且等于更高位数字(12) x当前

位数(100)。

如果百位上的数字为1,可知,百位上可能出现1的次数不仅受更高位影响,还受低位影响。例如对于12 113,受更高位影响,百位出现1的情况是100~199,1100~1199,2100~2 199,…,11100~11199,一共1200 个,等于更高位数字( 12) x当前位数(100)。但是它还受低位影响,百位出现1的情况是12 100~ 12 113,一共114个,等于低位数字(113) +1。

如果百位上数字大于1(即为2~9),则百位上可能出现1的次数仅由更高位决定,比如12213,则百位出现1的可能性为: 100~199,1100~1199,2 100~2 199,…,1,100~1199,12 10~12199,一共有1300个,并且等于更高位数字加1,再乘以当前位数,即(12+ 1) X100。

以上为《编程之美》中的原文,以下便是自己写的

#include<stdio.h>
int main()
{
	int N,lower=0,higher=0,dang=0;//lower低位,higher高位,dang当前
	int wei=1,sum=0;
	scanf("%d",&N);
	while(N/wei)
	{
		lower=N-N/wei*wei;
		dang=N/wei%10;
		higher=N/(wei*10);
		switch(dang)
		{
			case 0:
				sum+=higher*wei;
				break;
			case 1:
				sum+=higher*wei+lower+1;
				break;
			default:
				sum+=(higher+1)*wei;
				break;
		}
		wei*=10;
	}
	printf("%d\n",sum);
	return 0;
} 

    原文作者:小白求学进阶
    原文地址: https://blog.csdn.net/weixin_40295575/article/details/79514475
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞