题目描述:给定一个正整数N,写出从1到N所有整数,然后数一下其中出现的所有1的个数。
例如:
N=2, 写下1, 2 这样只出现一个1
N=12,写下1 ,2 ,3, 4, 5, 6, 7, 8, 9, 10, 11, 12.这样出现1的个数是5.
问题是写出一个函数f(N)表达1出现的个数,其中n 的大小为32位。
解答:
1. 最简单也是最蛮力的做法就是枚举,把每个数都找出其中出现1的个数
while(n!=0){
num+= (n%10==1)? 1:0;
n /= 10;
}
这种暴力的方法只适合于数据比较小的时候。时间的复杂度为Nlog2(N),
2.我们来仔细的归纳对于给定的N,似乎可以分析每一位上可能出现1的次数,之和来得到结果。假设N=13
十位出现1的个数 4
个位出现1的个数 2
F(N)= 4+2 = 6;
假设N=abcde, a,b,c,d,e分别表示十进制各个位数上的数字。如果要计算百位出现1的次数,它将会受到三个因素的影响。当百位,百位以下,百位以上。
如果百位为0, 则由高位决定,比如12013, 可知道百位出现1的个数100-199, 1100-1199, 2100-2199,。。。。11100-11199.一共是1200个。也就是高位数字12决定,12*100。
如果百位为1,则由高位12*100决定,并且有12100-12113,一共114个,等于地位113+1.
如果百位大于1,则由更高位决定,比如12213百位出现1 的可能个数100-199, 1100-1199, 2100-2199.。。。。。 12100-12199一共是1300个,并且等于更高位数字(12+1)*100
所以归纳出的代码是:
#include<iostream>
using namespace std;
int main() {
long long n;
cin>>n;
long long factor = 1;
long long low = 0;
long long curr = 0;
long long high = 0;
long long count = 0;
while(n/factor != 0) {
low = n - n/factor*factor;
curr = (n/factor)%10;
high = n/(factor*10);
switch(curr){
case 0:
count += high*factor;
break;
case 1:
count += high*factor + low + 1;
break;
default:
count += (high+1)*factor;
break;
}
factor *= 10;
}
cout<<count<<endl;
system("pause");
}