版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
题目描述
给定两个正整数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。
解法:记忆化搜索
#include<iostream>
#include<cstring>
#define ll long long
#define re register int
using namespace std;
ll a,b,num[15],f[15][2][15][2];
//len表示当前搜索的位数 issmall为当前位是否与num[len]相等 0相等 1不相等
//sum表示当前数字d出现的次数 zero表示之前是否是前导0 0是 1不是
//d为当前的数字
inline ll dfs(ll len,bool issmall,ll sum,bool zero,ll d) {
ll res=0;
if(!len) return sum;
if(f[len][issmall][sum][zero]!=-1) return f[len][issmall][sum][zero];
for(re i=0;i<10;i++) {
if(!issmall&&i>num[len]) break;
res+=dfs(len-1,issmall||i<num[len],sum+
((!zero||i)&&(i==d)),zero&&(!i),d);
}
f[len][issmall][sum][zero]=res;
return res;
}
inline ll solve(ll x,ll d) {
ll len=0;
while(x) {
num[++len]=x%10;
x/=10;
}
memset(f,-1,sizeof(f));
return dfs(len,0,0,1,d);
//从最高位开始搜索 与最高位相等 当前数字还没有出现
//之前不是前导0 当前搜索d
}
int main() {
cin>>a>>b;
for(re i=0;i<10;i++) {
cout<<solve(b,i)-solve(a-1,i)<<" ";
}
return 0;
}