数位DP…
写完自己已经不忍直视了,自己写的什么鬼这是…
写一下数位DP的“逐位确定”技巧:
在很多数位DP的题目中我们很容易得到一个数组f[],其中f[i]表示i位的满足题目要求的数的个数,即
[0,10i−1]
中满足题目要求的数的个数,具体数组的形式因题而异.
接下来要做的就是把所要求的
[0,k]
中满足题目要求的数的个数中的
[0,k]
分成若干个区间,以便用上f数组(好绕…).
举个例子如k=231可以分成[0 00,0 99],[1 00,1 99],[20 0,20 9],[21 0,21 9],[22 0,22 9],[230,230],[231,231]来分别计算所需答案,其中加粗部分即所谓“逐位确定”中的“位”,具体看代码.
注意a[1]=1时可能会有特殊情况!第一位为0时要特殊计算!
AC code:
#include <cstdio>
typedef long long ll;
const ll N=15;
ll a[3],len[3],ten[N]={1};
ll b[3][N],dig[3][N],ans[3][10];
void cal(ll num,ll x){
if(!x){
for(ll i=1;i<=len[num];i++) ans[num][dig[num][i]]++;
return ;
}
if(x==len[num]&&x!=1){
ans[num][0]=1;
for(ll i=x;i>=3;i--) ans[num][0]+=ten[i-3]*(i-2)*9;
for(ll i=1;i<10;i++) ans[num][i]+=ten[x-2]*(x-1);
}
for(ll i=(x==len[num]?1:0);i<b[num][x];i++){
dig[num][x]=i;
for(ll j=x;j<=len[num];j++) ans[num][dig[num][j]]+=ten[x-1];
if(x==1) continue;
for(ll j=0;j<10;j++) ans[num][j]+=ten[x-2]*(x-1);
}
dig[num][x]=b[num][x];
cal(num,x-1);
}
int main(){
scanf("%lld%lld",&a[1],&a[2]);
a[1]--;
for(ll i=1;i<=2;i++){
ll t=a[i];
if(!a[i]){
len[i]=1;
continue;
}
while(t){
b[i][++len[i]]=t%10;
t/=10;
}
}
for(ll i=1;i<=len[2];i++) ten[i]=ten[i-1]*10;
for(ll i=1;i<=2;i++) cal(i,len[i]);
for(ll i=0;i<10;i++){
printf("%lld",ans[2][i]-ans[1][i]);
if(i==9) printf("\n");
else printf(" ");
}
return 0;
}