难度:中等偏上
将1,2,3,…,n 每个数都看成是和n拥有相同位数的数字(比如下图,全部看成7位数),易知每一个数字的7位数字的组合都是各不相同的,因此每一种组合都对应一个不同的1到n之间的数字
如下图是具体思路
需要单独考虑x等于0的特殊处理
当x等于0时,需要特殊考虑两种情况:
(1) 0不可能出现在最高位,所以从len-2开始枚举
体现在代码中: for (int i = len - 1 - !x; i >= 0; i --)
(2) 考虑每一位上0的个数时不能再是从000 ~ abc-1,而是001 ~ abc-1,因为要保证当前0在数字中,而不是前导零中
if (!x) ans -= (int)pow(10, i);
易错:1.num数组中数字是从低位到高位存的 2.有可能a>b
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
int a, b;
// 得到一个数中某几个相邻的数字构成的数值
// 一定要记住从高位往低位遍历
int get_num(vector<int> num, int l, int r){
int ans = 0;
for (int i = l; i >= r; i --) ans = ans * 10 + num[i];
return ans;
}
// 计算1到n的所有的数中数字x出现的次数
int count(int n, int x){
vector<int> num;
while (n){
num.push_back(n % 10);
n /= 10;
}
int len = num.size(), ans = 0;
for (int i = len - 1 - !x; i >= 0; i --){ // 此处减去 !x 是精华
// 000 ~ abc-1
ans += get_num(num, len - 1, i + 1) * (int)pow(10, i);
if (!x) ans -= (int)pow(10, i); // x==0时,001 ~ abc-1
// abc
if (x == num[i]) ans += (get_num(num, i - 1, 0) + 1);
else if (x < num[i]) ans += (int)pow(10, i);
}
return ans;
}
int main(){
while (cin >> a >> b, a || b){ // a b 不全为0
if (a > b) swap(a, b);
for (int i = 0; i <= 9; i ++) printf("%d ", count(b, i) - count(a - 1, i));
puts("");
}
return 0;
}