题目描述
给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次。
输入输出格式
输入格式:
输入文件中仅包含一行两个整数a、b,含义如上所述。
输出格式:
输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次。
输入输出样例
输入样例#1: 复制
1 99
输出样例#1: 复制
9 20 20 20 20 20 20 20 20 20
说明
30%的数据中,a<=b<=10^6;
100%的数据中,a<=b<=10^12。
思路:稳妥点就用数位dp,那么记忆化搜索过程要记录什么状态呢?记录当前第几位和前面当前所求的数位之和就行了,然后注意前导0,因为前导0不算合法的位数。
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL dp[13][13], num[13];
int cur;
LL dfs(int pos, int lim, int zero, int sum)
{
if(pos == -1) return sum;
if(!zero && !lim && dp[pos][sum]+1) return dp[pos][sum];
int up = lim?num[pos]:9;
LL ans = 0;
for(int i=0; i<=up; ++i) ans += dfs(pos-1, lim&&i==num[pos], zero&&i==0, sum+(cur==0&&i==0&&!zero || cur&&i==cur));
if(!zero && !lim) dp[pos][sum] = ans;
return ans;
}
LL solve(LL x)
{
memset(dp, -1, sizeof(dp));
int cnt = 0;
while(x)
{
num[cnt++] = x%10;
x /= 10;
}
return dfs(cnt-1, 1, 1, 0);
}
int main()
{
LL a, b;
scanf("%lld%lld",&a,&b);
for(cur=0; cur<10; ++cur)
printf("%lld ",solve(b)-solve(a-1));
return 0;
}