传送门
多年以后再次写数位
d
p
dp
dp(
e
m
m
m
?
emmm?
emmm?
因为
0
0
0的问题处理不当还
w
a
wa
wa了一发
设
f
[
i
]
[
j
]
[
k
]
f[i][j][k]
f[i][j][k]表示前
i
i
i位第
i
i
i位为
j
j
j的数中
k
k
k出现了几次
然后前缀和转化一下
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define maxn 15
#define LL long long
using namespace std;
int n,a[maxn];
LL x,y,f[maxn][10][10],ans[maxn],tmp[maxn];
inline LL qpow(LL x,int k){
LL ret=1;
while(k){
if(k&1) (ret*=x);
(x*=x); k>>=1;
} return ret;
}
inline void solve(LL x){
int num=0; memset(tmp,0,sizeof tmp);
if(x==0) {tmp[0]=1;return;}
LL xx=x;
while(x){
a[++num]=x%10;
x/=10;
}
for(int i=num-1;i;i--)//高位不填,其余位随便填
for(int j=1;j<=9;j++)
for(int k=0;k<=9;k++)
tmp[k]+=f[i][j][k];
for(int j=a[num]-1;j;j--)//最高位不填满,其余位随便填
for(int k=0;k<=9;k++)
tmp[k]+=f[num][j][k];
for(int i=num-1;i;i--)//高位填满
for(int j=a[i]-1;j>=0;j--)
for(int k=0;k<=9;k++)
tmp[k]+=f[i][j][k];
for(int i=num;i>1;i--){
xx-=qpow(10LL,i-1)*a[i]; tmp[a[i]]+=xx;
}
}
int main(){
scanf("%lld%lld",&x,&y);
for(int i=0;i<=9;i++) f[1][i][i]=1;
LL xx=10;
for(int i=2;i<=12;i++){
for(int j=0;j<=9;j++){
for(int k=0;k<=9;k++){
for(int t=0;t<=9;t++)
f[i][j][k]+=f[i-1][t][k];
if(j==k) f[i][j][k]+=xx;
}
}
xx*=10;
}
solve(y+1);
for(int i=0;i<=9;i++) ans[i]=tmp[i];
solve(x);
for(int i=0;i<=9;i++) printf("%lld ",ans[i]-tmp[i]);
return 0;
}