BZOJ 1833 数位DP
思路:
数位DP
f[i][j][k]表示走到第i位 开头位j 数字k 出现的次数
$f[i][j][k]+=f[i-1][l][k];$
$f[i][j][j]+=base[i]$
calc的时候要有特殊的技巧...(我看题解学会的)
//By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define int long long int l,r,f[15][10][10],base[15],ans[10]; void calc(int m,int fl){ if(!m)return; int p=1,len=0; for(;10*p<=m;len++,p*=10); for(int i=1;i<=len;i++) for(int j=1;j<=9;j++) for(int k=0;k<=9;k++) ans[k]+=fl*f[i][j][k]; for(int j=1;j<m/p;j++) for(int k=0;k<=9;k++) ans[k]+=fl*f[len+1][j][k]; ans[m/p]+=fl*(m%p+1),m%=p,p/=10; for(int i=len;i;i--){ for(int j=0;j<m/p;j++) for(int k=0;k<=9;k++) ans[k]+=fl*f[i][j][k]; ans[m/p]+=fl*(m%p+1),m%=p,p/=10; } } signed main(){ scanf("%lld%lld",&l,&r),base[1]=1; for(int i=2;i<=13;i++)base[i]=base[i-1]*10; for(int i=1;i<=13;i++) for(int j=0;j<=9;j++){ for(int k=0;k<=9;k++) for(int l=0;l<=9;l++) f[i][j][k]+=f[i-1][l][k]; f[i][j][j]+=base[i]; } calc(l-1,-1),calc(r,1); for(int i=0;i<=9;i++){ printf("%lld",ans[i]); if(i!=9)putchar(' '); } }