与P2657 [SCOI2009] windy 数类似,都是通过枚举每一位上的数,这道题dp表示的是当前的数中含有数字dig的个数。
这次的代码在枚举过程中,参考了位运算的写法,更加简洁
#include<bits/stdc++.h>
using namespace std;
long long a,b;
long long dp[25][25][2][2];
int num[25];
long long ddp(int cnt,bool limit,bool lead,int dig,int v)
{
long long ans=0;
if(cnt==0) return v;
if(dp[cnt][v][limit][lead]!=-1 ) return dp[cnt][v][limit][lead];
for(int i=0;i<=9;i++)
{
if(!limit && i>num[cnt]) break;
ans+=ddp(cnt-1,limit||(i<num[cnt]),lead&&(i==0),dig,v+((!lead||i) && (i==dig)));
}
dp[cnt][v][limit][lead]=ans;
return ans;
}
long long solve(long long x,int c)
{
memset(dp,-1,sizeof(dp));
int len=0;
while(x)
{
num[++len]=x%10;
x/=10;
}
return ddp(len,0,1,c,0);
}
int main()
{
scanf("%lld%lld",&a,&b);
for(int i=0;i<=9;i++)
printf("%lld ",solve(b,i)-solve(a-1,i));
return 0;
}