题目:
题解:
感觉一直不会这类dp
f[i][j][k]表示i位数以j开头,k数字出现的次数
代码:
#include <cstdio>
#include <cstring>
#define LL long long
using namespace std;
struct hh
{
LL a[10];
void clear(){memset(a,0,sizeof(a));}
}f[15][10];
LL t[15];int digit[15];
hh operator +(hh a,hh b)
{
hh c;
for (int i=0;i<=9;i++) c.a[i]=a.a[i]+b.a[i];
return c;
}
hh work(LL a)
{
int cnt=0;LL wh=a;
while (wh) digit[++cnt]=wh%10,wh/=10;
hh c;c.clear();
c.a[0]=1;
if (a==0) return c;
for (int i=1;i<cnt;i++)//最高位为0
for (int j=1;j<=9;j++) c=c+f[i][j];
for (int i=1;i<digit[cnt];i++) c=c+f[cnt][i];//最高位不为0
a%=t[cnt]; c.a[digit[cnt]]+=a+1;//最高位不为0紧贴上界
for (int i=cnt-1;i>=1;i--)
{
for (int j=0;j<digit[i];j++)
c=c+f[i][j];
a%=t[i];
c.a[digit[i]]+=a+1;
}
return c;
}
int main()
{
t[1]=1; for (int i=2;i<=12;i++) t[i]=t[i-1]*10;
for (int i=0;i<=9;i++) f[1][i].a[i]=1;
for (int i=2;i<=12;i++)
for (int j=0;j<=9;j++)
for (int k=0;k<=9;k++)
{
f[i][j]=f[i][j]+f[i-1][k];
f[i][j].a[j]+=t[i-1];
}
LL a,b;
scanf("%lld%lld",&a,&b);
hh t1=work(a-1);
hh t2=work(b);
for (int i=0;i<=9;i++)
printf("%lld ",t2.a[i]-t1.a[i]);
}