感受
整数分块真香!


思路
一般询问区间[L, R]的问题要么直接处理,要么分成[1, R]-[1, L - 1]处理。
直接考虑第二种处理方法,怎么求[1,x]的答案呢?



比如我们想求解约数的最高位的那个数码为4的情形

  1. 4
  2. [40, 49]
  3. [400, 499]
    ...
    有什么用呢?
    如果一个约数为q,那么区间[1, n]中存在约数为q的有【n/q】(下取整)
    是不是想到了,这不是就是傻×分块吗?

复杂度分析
枚举数码O(9)

  • 枚举数码对应的区间
  • 对于每一个区间,进行整数分块求解
    总复杂度最坏为O(9 * 10 * sqrt(n))= O(1e6)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e4 + 10;
ll l, r;
ll solve(ll n, ll i){
    ll ans = 0; ans += n / i;
    ll f = i * 10; ll top = i * 10 + 9; top = min(top, n);
    ll num;
    for(; f <= n; f *= 10, top = top * 10 + 9, top = min(top, n)){
        for(ll L = f, R; L <= top; L = R + 1){
            num = n / L;
            R = n / num; R = min(top, R);
            ans += num * (R - L + 1);
        }
    }
    return ans;
}
int main(){
    scanf("%lld%lld", &l, &r);
    for(ll i = 1; i <= 9; i++){
        printf("%lld\n", solve(r, i) - solve(l - 1, i));
    }
    return 0;
}