太久没写博客了呀
这篇文章的精华代码只是在大神的基础上加了注释 勉强弄懂 感谢John_Cc大神
/*
#include <iostream>
using namespace std;
int count_1(int num){
int i = 0;
while(num){
if(num % 10 == 1){
i++;
}
num /= 10;
}
return i;
}
int main()
{
int n;
int num = 0;
cin >> n;
for(int i=1; i<=n; i++){
num += count_1(i);
}
cout << num << endl;
return 0;
}
*/
///progress:
///用乘法比pow()快~~~~
/// 高效率版本,时间复杂度 O(logn);
///这个不是通过计算每个数1的个数然后加起来 这样就省了一个for循环 这样就减小了时间复杂度
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int PowerBase10(unsigned int n)
{
int result = 1;
unsigned int i = 0;
for(i = 0; i < n; ++i )
result *= 10;
return result;
}
int NumberOf1(const char *strN)
{
int first = *strN - '0';
int numFirstDigit = 0;
///numFirstDigit 是数字10000 ~ 19999 的第一个位中的数目;
int num0therDigits = 0;
///num0therDigits 是1346 ~ 21345除了第一位之外的数位中的数目;
int numRecursive = 0;
///numRecursive 是1 ~ 1345 中的数目;
unsigned int length = strlen(strN);
if(!strN || *strN < '0' || *strN > '9' || *strN == '\0')
return 0;
if(length == 1 && first == 0)
return 0;
if(length == 1 && first > 0)
return 1;
if(first > 1)
numFirstDigit = PowerBase10(length - 1);///假设strN 是"21345", 10000~19999
else if(first == 1)
numFirstDigit = atoi(strN + 1) +1; /// 以11345为例 10000~11345 共1346个
///1346~21345 除了第一位之外的数位的数目
num0therDigits = first * ( length - 1) * PowerBase10(length - 2);/// 2* 4 * 10*10*10
///1~1345
numRecursive = NumberOf1(strN + 1);///
cout << numFirstDigit << endl;///上面是一个递归, 45 所以是10 345 所以是 100 1345 所以是 1346
return numFirstDigit + num0therDigits + numRecursive;
}
int NumberOfBetween1AndN(int n)
{
char strN[50];
if(n < 0)
return 0;
sprintf(strN,"%d",n);
return NumberOf1(strN);
}
int main()
{
printf("%d\n",NumberOfBetween1AndN(11345));
///system("pause"); 请按任意键继续...
return 0;
}