对于大范围  内的数字统计,需要使用数位DP的方法:

  1. 将问题转化为求 ,表示  到  中每个数字出现的次数则区间  的答案为 
  2. 对于计算 :考虑每一位的贡献例如对于数字 :个位:每  个数, 各出现  次十位:每  个数,每个数字在十位上出现  次百位:每  个数,每个数字在百位上出现  次千位: 出现  次, 出现  次, 出现  次
  3. 核心思路:对每一位,计算该位上的每个数字出现次数需要考虑当前位是否受限
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;

// 计算每个数字在1到n中出现的次数
vector<ll> count_digits(ll n) {
    vector<ll> cnt(10, 0);
    ll pos = 1;  // 位权:1, 10, 100, ...
    
    while (n >= pos) {
        ll high = n / (pos * 10);  // 高位数字
        ll curr = (n / pos) % 10;  // 当前位数字
        ll low = n % pos;          // 低位数字
        
        // 对0-9每个数字统计在当前位出现的次数
        for (int digit = 0; digit < 10; digit++) {
            // 计算当前位之前的完整循环次数
            cnt[digit] += high * pos;
            
            // 处理当前位
            if (digit < curr) {
                cnt[digit] += pos;
            } else if (digit == curr) {
                cnt[digit] += low + 1;
            }
            
            // 处理前导零的特殊情况
            if (digit == 0) {
                cnt[0] -= pos;  // 减去前导零的情况
            }
        }
        
        pos *= 10;
    }
    
    return cnt;
}

int main() {
    ll a, b;
    cin >> a >> b;
    
    // 计算[1,b]和[1,a-1]的统计结果
    vector<ll> cnt_b = count_digits(b);
    vector<ll> cnt_a = count_digits(a - 1);
    
    // 输出[a,b]区间的结果
    for (int i = 0; i < 10; i++) {
        cout << cnt_b[i] - cnt_a[i] << " ";
    }
    cout << endl;
    
    return 0;
}