题目描述
解题思路:偏思维的一道题目。
对于1的位数统计,可以考虑每个位上1出现的次数。那么从1~N中1出现的个数就可以转化为每位上1出现的次数的总和。
对于某一位中,1出现的次数计算方式如下:
如:abcdefg这个数,现要统计d这个数字这一位上1出现的次数。
记d右边总共有k位
考虑三种情况:
(1) d为0,则左边可能数字出现的情况为0~abc-1 右边可能数字出现的情况为10^k。则总共出现的次数为abc * (efg+1)
(2) d为1,则左边可能数字出现的情况为0~abc-1 右边可能出现的情况为10^k 并且加上 左边出现的数字为 abc 右边出现的数字情况为0~efg。则总共出现的次数为abc*10^k + efg+1
(3)d>1,则左边可能出现的情况为0~abc,右边可能出现的情况总数为10^k,则总次数为(abc+1)*10 ^ k
疑惑点:1. 如果从0开始统计,是否会造成数字重复统计。答案是不会的,例如 0002123 与 0020123 左边是0 右边是123 结果是不一样的 正是因为所在的位不同,所以必定不可能会出现一样的数字造成重复统计。2. 当取第1位的时候,公式规律会不会不成立。答案是不会的,取第1位的时候,d不可能是0,这就使得left虽然等于0,但是带进去仍然符合要求。
#include<iostream>
using namespace std;
int main(){
int n,k=1,res=0,left=0,right=0;
cin>>n;
while(n/k){
left = n/k/10;
right = n%k;
int d = n/k%10;
if(d == 0) res += left*k;
else if(d == 1) res += left*k + right + 1;
else res += (left+1)*k;
k*=10;
}
cout<<res;
return 0;
}