/*
从1到n的n个数字 十进制表示 1出现的次数 肯定是数学题找规律呗
比如输入数字是21345 分而治之
1-1345 1346-21345
先求第二段 万位是 一共1w个
然后再分称1346-11345 11346-21345 每段的四个数字中 其中一个是1 其余10^3所以一共两千
就这么分
这个代码 理解的将就吧。。。反正就是把数字拆分开求
又看了两便理解了。 书上有写错的地方 第一次在这本书发现错
*/
#include<cstring>
#include<iostream>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std;
int NumberOf1(const char * str)
{
if(!str || *str<'0' || *str>'9' || *str=='\0')
return 0;
int first=*str-'0';
unsigned int len=static_cast<unsigned int>(strlen(str));
if(len==1 && first==0)
return 0;
if(len==1 && first>0)
return 1;
int numFirstDigit=0;
if(first>1)
numFirstDigit=(int)pow((double)10,(double)len-1);
else if(first==1)
numFirstDigit=atoi(str+1)+1;//atoi函数竟然在stdlib里面!!!!
//这里关于为什么要乘len-1理解了半天 书前面写错了,因为在除了最高位外任意一位选择1一个 设为一 所以成
int numOtherDigits=first*(len-1)*(int)pow((double)10,(double)(len-2));
int numRecursive=NumberOf1(str+1);
return numFirstDigit+numOtherDigits+numRecursive;
}
int NumberOf1Between1AndN(int n)
{
if(n<=0)
return 0;
char str[50];
sprintf(str,"%d",n);
return NumberOf1(str);
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
cout<<NumberOf1Between1AndN(n)<<endl;
}
return 0;
}