数字统计类题目的非数位DP解法

ZJOI2010 数字统计

上题题意为求[l,r]区间中每个数字(0~9)出现的次数

一般的做法为将区间当成[0,r]-[0,l-1],然后进行数位DP
但事实上将区间当成[0,r]-[0,l-1]后可以有另一种方法求出[0,x]中k出现的次数

具体做法:

我们对于每一位,求出k在这一位的数中有多少小于等于x,累加即可。(注意0不能前导,要分开处理)

#define ll long long
inline ll query(ll x,int k){//询问[0,x]的数字中k出现的次数 
    if(x<0)return 0;
    ll sum=0,a=1,i=1,s=1,x1;
    while(x/10){//枚举k出现在每一位 
        i=x%10,x/=10;//i表示k出现的这一位在原数中是什么,x表示原数中i之前的数字 
        x1=x;
        if(!k) x1--;//因为不能有前导零,所以0要分开 
        if(i>k)sum+=s*(x1+1);//3种情况分类讨论 
        else if(i==k)sum+=s*x1+a;
        else sum+=s*x1;
        a+=i*s,s*=10;//a表示原数中i之后的数字+1 
    }
    if(!k)return sum+1;//为k为0就无法做第一位 
    else{//考虑x做第一位的情况 
        if(x>k)return sum+s;
        if(x==k)return sum+a;
        return sum;
    }
}

 

posted @ 2017-12-15 09:33  Bennettz  阅读(186)  评论(0编辑  收藏  举报