码迷,mamicode.com
首页 > 其他好文 > 详细

从1到n的数中总共包含1的个数

时间:2015-03-30 23:12:02      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:递归

1. 题目

求从1到n的数中,总共包含了多少个1

2. 分析

令X=x1x2…xm为1到n之间的一个整数,显然X为一个m位的整数。例如X=21345时,对应x1=2,x2=1,x3=3,x2=4,x3=5。题目求解过程如下:

(1) 将X分成0~X1与X1+1~X两部分,其中X1=x2…xm若此时X只有一位则X1=0,实际实现时用字符串表示数字X,当X只有一位时移至字符串末尾’\0’

(2) 第二部分X1+1~X分为3种情况求解:

a) x1 > 1,

a_1) 最高位为1的共p1=10m-1次;

a_2) 其它低位为1共p2=x1*(m-1)*10m-2,这里需要注意的是1的次数不可能出现小数,因此当m-2<0是需要定义10m-2=1。

b) x1=1,

b_1) 最高位是1的共p1=X1+1次(注意这里不是x1);

b_2) 其它低位为1的共p2=x1*(m-1)*10m-2,这里需要注意的是1的次数不可能出现小数,因此当m-2<0是需要定义10m-2=1。

c) x1=0,对应a)、b)有p1=p2=0。

(3) 令X=X1,若X的位数大于1则递归执行(1)(2);反之运行结束。

以上求解过程中重在理解a_2)中p2的计算,参考理解思路:

(1) 将第二部分分为[xjx2…xm, (xj+1)x2…xm]共x1个区间,其中0≤xj≤xj + 1 ≤x1

(2) 对于每个区间在非最高位任意位置选择一个位置放1,共m-1种。

(3) 任意位置放置1后,其它m-2个位置可以任意放置0~9,共10m-2种。

综上,p2=x1*(m-1)*10m-2

对于b_2)的理解与a_2)相似。

3. 参考代码

#include <iostream>
using namespace std;

int powerBase10(int n)
{
	int result = 1;
	if (n > 0)
	{
		for (unsigned int i = 0; i < n; ++i)
		{
			result *= 10;
		}
	}
	
	return result;
}

int numberOf1(const char *strN)
{
	if (!strN || *strN < '0' || *strN > '9' || *strN == '\0')
	{
		return 0;
	}
	int first = *strN - '0';
	unsigned int length = strlen(strN);

	int numFirstPart = 0;
	if (first > 1)
	{
		numFirstPart = powerBase10(length - 1);
	}
	else if (1 == first)
	{
		numFirstPart = atoi(strN + 1) + 1;
	}
	int numSecondPart = first * (length - 1) * powerBase10(length - 2);
	return numFirstPart + numSecondPart + numberOf1(strN + 1);
}

int numberBetween1AndN(int n)
{
	if (n <= 0)
	{
		return 0;
	}
	char strN[50];
	sprintf(strN, "%d", n);
	return numberOf1(strN);
}
int main()
{
	int n = 50;
	cout << numberBetween1AndN(n) << endl;
	return 1;
}


从1到n的数中总共包含1的个数

标签:递归

原文地址:http://blog.csdn.net/woniu317/article/details/44758339

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!