analysis
好久没碰blog了
这是所谓数位DP
数位dp是一种计数用的dp,一般就是要统计一个区间[l,r]内满足一些条件数的个数,这个条件一般都与大小无关(这不废话?不然还能叫DP?)
然后对于这道题,使用记忆化搜索可以解决问题(记忆化搜索其实也是DP),即从高位到低位在限制范围内枚举可能性,然后记忆化一下,最后得解
(感觉还没有把这东西学透)
code
#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a<b)?a:b)
#define ll long long
ll dp[19][19],num[19];
ll dfs(register int pos,register bool lim,register bool lead,register int sum,register int dig){
register ll res=0;register int up=((lim)?num[pos]:9);
if(lead&&!lim&&dp[pos][sum]!=-1)return dp[pos][sum];if(!pos)return sum;
loop(i,0,up)res+=dfs(pos-1,lim&&(i==up),lead||i,sum+((i||lead)&&(i==dig)),dig);
if(lead&&!lim)dp[pos][sum]=res;return res;
}
inline ll work(register ll a,register int b){
clean(dp,-1);register int cnt=0;
while(a)num[++cnt]=a%10,a/=10;
return dfs(cnt,1,0,0,b);
}
int main(){
register ll a,b;scanf("%lld%lld",&a,&b);
loop(i,0,9)printf("%lld ",work(b,i)-work(a-1,i));
return 0;
}