题目描述
给定两个正整数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 <cstdio>
#include <algorithm>
#include <cmath>
#include <set>
#include <cstring>
#include <stack>
#include <set>
#include <vector>
#include <queue>
#define Swap(a,b) a ^= b ^= a ^= b
#define cl(a,b) memset(a,b,sizeof(a))
using namespace std ;
typedef long long LL;
const int N = 1e7+10 ;
LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
const int MAX = 105;
const int inf = 0xffffff;
const LL mod = 1e9+7 ;
priority_queue<int,vector<int>,greater<int> > q ;// 小跟堆
priority_queue<int> Q ; // 大堆
LL a[20] ;
LL dp[20][20] ;
LL dfs(int pos , bool limit , bool lead , int dig ,LL sum){
// limit为1 表示有限制 , lead 为0 表示有 前道0
LL ans = 0 ;
if(pos == 0 ){
return sum ;
}
if(!limit&& lead&&dp[pos][sum]!=-1){// 合法
//记忆化
return dp[pos][sum] ;
}
int up = limit ?a[pos]:9;// 如果该位有限制,就设为a[pos],否则,0~9都可以呀
for(int j = 0 ; j<=up ;j++){
ans+=dfs(pos-1,(j==up)&&limit ,lead||j ,dig,sum+((j||lead)&&(j==dig)));
}
if(!limit&&lead){
dp[pos][sum] = ans ;
}
return ans ;
}
LL solve(LL x ,int d){
int pos = 0 ;
memset(dp,-1,sizeof(dp)); // 初始化
while(x){
a[++pos]=x%10;
x/=10 ;
}
return dfs(pos,1,0,d,0);
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL),cout.tie(NULL);
LL l , r ;
cin >> l >>r ;
for(int i = 0 ; i<=9 ; i++ ){
cout<<solve(r,i)-solve(l-1,i)<<" ";
}
return 0;
}