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;
}