分类讨论
状态表示:$f[mid][target]$ 当前位数mid的targe出现的次数
1. 将数字放入数组 $nums: [个位…最高位]$,从高位开始枚举
2. 将数字拆分为三段:$high : mid : low$
3. 每段的区间:$high: [m, i + 1], mid: i ,low: [i - 1, 0]$
4. 记录high所在位数:$power = 10^i$
分析target在mid位出现的次数
- $mid == target: target$ 出现的次数为数字的值为 $high * power + low + 1$ (0 - [height 0 000] - [high target low] )
- $mid > target : high * power + power$ (0 - [ height 0 000] - [high target 000])
- $mid < target : mid位置不会出 现target,高位会出现:high * power$ (0 - [high 0 000])
- 特殊情况 $target == 0$ 只统计到( 0 - [height-1 0 000])
C++ 代码
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
int GetNum(vector<int>& nums, int l, int r){
int res = 0;
for(int i = l; i >= r; i--){
res = res * 10 + nums[i];
}
return res;
}
int CountTimesOfTarget(int n, int target){
if(n == 0) return 0;
vector<int> nums;
//先将数字存入数组
while(n){
nums.push_back(n % 10);
n /= 10;
}
int res = 0;
int m = nums.size() - 1;
for(int i = m; i >= 0; i--){
int mid = nums[i];
int power = pow(10, i);
int high = GetNum(nums, m, i + 1);
int low = GetNum(nums, i - 1, 0);
res += high * power;
if(target == 0) res -= power;
if(mid == target) res += low + 1;
else if(mid > target) res += power;
}
return res;
}
int main(){
int a, b;
while(cin >> a >> b, a || b){
if(a > b) swap(a, b);
for(int i = 0; i < 10; i++){
//计算i出现的次数
if(i) cout << " ";
cout << CountTimesOfTarget(b, i) - CountTimesOfTarget(a - 1, i);
}
cout << endl;
}
}