题目描述
给定一个整数n,返回从1到n的数字中1出现的个数。
例如:
n=5,1∼n为1, 2, 3, 4, 5。那么1出现了1次,所以返回1。
n=11,1∼n为1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11。那么1出现的次数为1(出现1次),10(出现1次),11(有两个1,所以出现了2次),所以返回4。
输入描述:
输入一个整数N。
输出描述:
输出一个整数表示答案
示例
输入
2345
输出
1775
备注:
1⩽N⩽10^13
算法:
固定某一位为1,看其他位置可以变化的范围,其次使用递归将大的问题转换成小的子问题,比如21345划分成1-1345,1346-21345。
注意:每个要处理数字的最高位要特殊处理一下。
//O(logn*logn)
#include<bits/stdc++.h>
using namespace std;
int numDigits(long long num){
int len=0;
while(num){
len++;
num/=10;
}
return len;
}
long long solution(long long n){
if(n<1){
return 0;
}
int len=numDigits(n);
if(1==len){
return 1;
}
long long base=pow(10,len-1);
long long first=n/base;
long long firstDigitHas1 = first==1 ? n%base+1 : base;
long long otherDigitHas1 = first*(len-1)*(base/10);
return firstDigitHas1+otherDigitHas1+solution(n%base);
}
int main(){
long long n;
cin>>n;
cout<<solution(n)<<endl;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
class Solution{
private:
int numDigits(long long num){
int len=0;
while(num){
len++;
num/=10;
}
return len;
}
public:
long long countOf1(long long n){
if(n<1){
return 0;
}
int len=numDigits(n);
if(1==len){
return 1;
}
long long base=pow(10,len-1);
long long first=n/base;
long long firstDigitHas1 = first==1 ? n%base+1 : base;
long long otherDigitHas1 = first*(len-1)*(base/10);
return firstDigitHas1+otherDigitHas1+countOf1(n%base);
}
};
int main(){
long long n;
cin>>n;
Solution sol;
cout<<sol.countOf1(n)<<endl;
return 0;
}