图片说明
数论分块,那么咋分呢?我们先手动一发。
比如此时r=66.我们要求1的出现次数那么就是1,[10,20)
66/1 = 66 , 而66/66 = 1,代表从[1,1]只有1个数最高位为1
66/10=6,66/6=10,代表从[10,10]有1个数高位为1
66/11=6,66/6=11,代表[11,11]有1个数高位为1
66/12=5,66/5=13,代表[12,13]有2个数高位为1
66/14=4,66/4=16,代表[14,16]有3个数高位1
66/17=3,66/3=22,22>20代表[17,20)有3个高位1

至此我们就可以看出了如何去分。要求出[l,r]中我们就换成求出 [i,r]-[i,l-1] (1<=i<=9),那么就模拟一遍过程就可以了。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <set>
#include <sstream>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<cmath>
#include<cctype>
#include<cstring>
#include<cstdlib>
#define MAXX 100005
#define SIS std::ios::sync_with_stdio(false)
#define ll long long
#define INF 0x3f3f3f3f
//#include<bits/stdc++.h>
using namespace std;
const int MAX =1e5+6;
const double PI = 3.14159265359;
//const int mod = 1e9 + 7;

ll a[MAX];
ll sum[MAX];
ll solve(ll r,ll x)
{
    ll ans=r/x;
    ll st=x*10,en=min(r,x*10+9);///先求出左右区间
    for(;st<=r;st*=10,en=en*10+9)
    {
        ll k=min(en,r);///在边界内
        for(ll i=st;i<=k;)
        {
            ll sum=r/i;
            ll mx=min(r/sum,k);
            ans+=sum*(mx-i+1);
            i=mx+1;///更新区间
        }
    }
    return ans;
}
int main()
{
  SIS;
  ll l,r;
  cin>>l>>r;
  for(int i=1;i<=9;i++)
  {
    cout<<solve(r,i)-solve(l-1,i)<<endl;
  }

}