The Counting Problem UVA - 1640

点击打开链接

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

/*
这道题写的自己差点吐血,真是服了,差点放弃

1.前导0 记录直接zero&&i==0,就好了,只不过,没想到他在后面的记忆化中,没有注意
        导致0的数量一直都是少的,我们一开始统计的都是没有前导0的,可是后面只要
        补上一个数,就会出现比之前多余的0,所以也要记录一下
2.树形模型  其实就是状态压缩么,要不怎么会节约时间呢
3.dp[pos][bit]  没有limit的情况下,在pos最大为bit的情况下的总数量,要理解数组的含义
*/

int pow_(int base,int n){
    int ans=1;
    for(int i=1;i<=n;i++)
        ans*=base;
    return ans;
}

int dp[10][10][10];
int cnt;
int bit[10];

int get_num(int pos){
    int ans=0;
    for(int i=pos-1;i>=0;i--){
        ans=ans*10+bit[i];
    }
    return ans;
}


int dfs(int pos,int limit,int val,int zero,int bb){//当前数字取某一个特定的值
    if(pos==-1){//0的特殊之处
        if(zero&&bb==0)return 1;//如果是0的数量
        return 0;
    }

    if(!limit&&!zero&&dp[pos][val][bb]!=-1){
        return dp[pos][val][bb];
    }

    int max_num=limit?bit[pos]:9;
    int sum=0;//计算 在当前最大值为val的前提下,特定数字的总数量!!!
    for(int i=0;i<=max_num;i++){
        if(zero&&i==0)
            ;
        else if(i==bb){//统计当前位就是 需要的值
            if(limit&&i==max_num)
                sum+=get_num(pos)+1;
            else
                sum+=pow_(10,pos);
        }
        sum+=dfs(pos-1,limit&&i==max_num,i,zero&&(i==0),bb);//统计下面所有层的总和
    }
    if(!limit&&!zero)dp[pos][val][bb]=sum;//当前位置为最大值 val的前提下,特定数字的总数量!!!前导0
    return sum;
}

int ans1[10],ans2[10];
void solve(int num,int flag){
    cnt=0;
    while(num){
        bit[cnt++]=num%10;
        num/=10;
    }
    if(flag){
        for(int i=0;i<10;i++)ans1[i]=dfs(cnt-1,1,bit[cnt-1],1,i);
    }
    else{
        for(int i=0;i<10;i++)ans2[i]=dfs(cnt-1,1,bit[cnt-1],1,i);
    }
}
/*
1 10
44 497
346 542
1199 1748
1496 1403
1004 503
1714 190
1317 854
1976 494
1001 1960
0 0
*/
int main()
{
    memset(dp,-1,sizeof(dp));
    int a,b;
    while(scanf("%d %d",&a,&b)==2){
        if(a==0&&b==0)break;
        if(a>b)swap(a,b);

        solve(b,1);
        solve(a-1,0);
        for(int i=0;i<10;i++){
            if(i==0) printf("%d",ans1[i]-ans2[i]);
            else printf(" %d",ans1[i]-ans2[i]);
        }
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36424540/article/details/81037346