您的位置:首页 > 其它

统计1到N之间所有十进制数中数字1的个数。

2013-03-03 19:27 260 查看
这是一道十分有趣的题,例如N为12的时候,输出是5,因为从1到12,总共有1,10,11,12中包含数字1,总共是5个。

最傻逼的办法当让是直接枚举,即N^2的方法,对于小数据,是可以容忍的,但是此题中N最大可以达到2^30次方,因此

该方法不行。

我觉得这一题更偏数学一点,只要找到了递推公式,变成是非常简单的。

我们用part1来表示1-99..99中所包含的1的个数

1-9中有只有1一个

1-99总共有20个

递推公式很容易得到,part1
= part1[n-1]*10 + 10^(n-1),其中N表示9的个数。

对于N,我们从N的个位数开始往高位递推。

如下图所示



假设我们已经进行到n位,我们用part2表示前n位的结果。N的第n位数字是t,那么前N位的结果

part2
= part2[n-1] + t*part1[n-1]。

如果t = 1,那么还要再加上N mod (10^(n-1))的结果,如果t>1,加上10^(n-1)的值即可。

代码如下:

#include<iostream>
using namespace std;

int main()
{
unsigned long n;
unsigned long part1,part2,ans,yu;
unsigned long base = 1;
unsigned int tmp;
cin >> n;
base = 1;        //用来表示10的几次方
ans = 0;        //用来存储最终的结果
yu = n%10;        //用来表示N mod (10^(n-1))的结果,即余数
part1 = 1;        //表示part1
if (yu >= 1) ans = 1;
part2 = ans;     //表示part2
n = n/10;
while (n!=0){
tmp = n % 10;
base = base*10;
ans = tmp*part1 + part2;
if(tmp == 1) ans = ans + yu + 1;
else if (tmp > 1) ans = ans + base;
part1 = part1*10 + base;
part2 = ans;
n = n/10;
yu = tmp*base + yu;
}
cout << ans<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐