题意
给出正整数n,计算出所有小于等于n的正整数中1的个数。
For example, given N being 12, there are five 1's in 1, 10, 11, and 12.
思路
依次分析每一位为1所对应的整数个数。
记now为当前位的数字,left为当前位左边的数字,right为当前位右边的数字,d为分析位(1表示个位,10十位,100百位 ...)。
1、当now=0时,因为此时该位不为1,我们需要让它为1,此时左边可取的范围为0~left-1(若是左边取left,那么就大于了n),那么右边取值的范围呢?右边取值是随意的,即0~d-1,因为此时肯定不会大于最大值,例当前d为10,那么右边的取值为0~9。故该位为1的整数共有left*d个。
2、当now=1时,此时该位已经等于1,左边可取的范围为0~left,当左边为0~left-1时,右边取值范围为0~d-1。当左边为left时,由于不能大于n,右边取值范围为0~right。故该位为1的整数共有left*d+right+1个。
3、当now>=2时,同理左边取值范围为0~left,右边为0~d-1。该位为1的整数共有(left+1)*d个。
代码
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 5 6 int main(){ 7 //freopen("in.txt", "r", stdin); 8 int n; 9 scanf("%d", &n); 10 int d = 1; 11 int res = 0; 12 while(n/d){ 13 int now = n/d%10; 14 int left = n/d/10; 15 int right = n%d; 16 if(now == 0){ 17 res += left*d; 18 } 19 else if(now == 1){ 20 res += left * d + right + 1; 21 } 22 else{ 23 res += (left+1) * d; 24 } 25 d *= 10; 26 } 27 printf("%d ", res); 28 return 0; 29 }