UVA 1640 The Counting Problem UVA1640 求[a,b]或者[b,a]区间内0~9在里面各个数的数位上出现的总次数。

时间:2023-03-09 08:17:52
UVA 1640 The Counting Problem UVA1640 求[a,b]或者[b,a]区间内0~9在里面各个数的数位上出现的总次数。
/**
题目:UVA 1640 The Counting Problem UVA1640
链接:https://vjudge.net/problem/UVA-1640
题意:求[a,b]或者[b,a]区间内0~9在里面各个数的数位上出现的总次数。
思路:数位dp;
dp[leadzero][i][j][k]表示前面是否选过非0数,即i长度之后可以第一个出现0,而不是前导0,长度为i,前面出现j,k次,j出现的次数。
*/ #include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<set>
#include<cmath>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf = 0x3f3f3f3f;
const int maxn = 1e5+;
int dp[][][][];///dp[leadzero][i][j][k]表示前面是否选过非0数,即i长度之后可以第一个出现0,而不是前导0,长度为i,前面出现j,k次,j出现的次数。
int digit[];
ll n;
int l[], r[];
int dfs(int leadzero,int len,int value,int bounded,int cnt)
{
if(len==){
return cnt;
}
if(!bounded&&dp[leadzero][len][value][cnt]!=-) return dp[leadzero][len][value][cnt];
int d = bounded?digit[len]:;
int ans = ;
for(int i = ; i <= d; i++){
if(leadzero){
ans += dfs(,len-,value,bounded&&(i==d),cnt+(i==value));
}else
{
if(i==)
ans += dfs(,len-,value,bounded&&(i==d),cnt);
else
ans += dfs(,len-,value,bounded&&(i==d),cnt+(i==value));
} }
if(!bounded){
dp[leadzero][len][value][cnt] = ans;
}
return ans;
}
void cal(int n,int x[])
{
int len = ;
while(n){
digit[++len] = n%;
n /= ;
}
for(int j = ; j < ; j++){
x[j] = dfs(,len,j,true,);
}
}
int main()
{
int a, b;
memset(dp, -, sizeof dp);
while(scanf("%d%d",&a,&b)==)
{
if(a==&&b==) break;
if(a>b) swap(a,b);
cal(a-,l);
cal(b,r);
for(int i = ; i < ; i++){
printf("%d ",r[i]-l[i]);
}
printf("%d\n",r[]-l[]);
}
return ;
}