传统数位dp思想,分位统计f[i][j][k]表示一个长i位的数第一位为j 到0 中字符k出现的次数。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <queue>
using namespace std;
long long f[13][10][10],fac[20];
struct node
{
long long a[10];
}t1,t2;
void init()
{
fac[1]=1;for(int i=2;i<=13;i++) fac[i]=fac[i-1]*10;
for(int i=0;i<=9;i++) f[1][i][i]=1;
for(int i=2;i<=12;i++)
{
for(int j=0;j<=9;j++)
{
for(int k=0;k<=9;k++)
{
for(int p=0;p<=9;p++)
{
f[i][j][p]+=f[i-1][k][p];
}
f[i][j][j]+=fac[i-1];
}
}
}
}
node get(long long x)
{
node ans;for(int i=0;i<=9;i++)ans.a[i]=0;
if(!x)
{
ans.a[0]=1;
return ans;
}
int len=1;
for(;x>=fac[len];len++);
len--;
for(int i=1;i<len;i++)
{
for(int j=1;j<=9;j++)
{
for(int k=0;k<=9;k++)
{
ans.a[k]+=f[i][j][k];
}
}
}
ans.a[0]++;
int cur=x/fac[len];
for(int i=1;i<cur;i++)
for(int j=0;j<=9;j++)
ans.a[j]=ans.a[j]+f[len][i][j];
x%=fac[len];
ans.a[cur]+=x+1;
for(int i=len-1;i;i--)
{
cur=x/fac[i];
for(int k=0;k<cur;k++)
for(int j=0;j<=9;j++)
ans.a[j]=ans.a[j]+f[i][k][j];
x%=fac[i];
ans.a[cur]+=x+1;
}
return ans;
}
int main()
{
init();
long long a,b;
cin>>a>>b;
t1=get(b);
t2=get(a-1);
for(int i=0;i<=9;i++)
{
printf("%lld",t1.a[i]-t2.a[i]);
if(i!=9)printf(" ");
}
return 0;
}