动态规划:数位统计DP

#include
#include
#define ll long long

using namespace std;

int get(vectornum,int l,int r)//求该位之前的所有位组成的数 
{
    int res=0;
    for(int i=l;i>=r;i--)
        res=res*10+num[i];
    return res;
}

int power10(int x)//求10的该位之后的位数次方
{
    int res=1;
    while(x--)res*=10;
    return res;
}

ll count(int n,int x)//返回从1~n所有数中x出现的总数
{
    if(!n) return 0;//若n是0则直接返回
    
    vectornum;//把n的每一位抠出来
    while(n)
    {
        num.push_back(n%10);
        n/=10;
    }
    
    n=num.size();//让n为数字的总位数,后面n就是这个数字的位数用来操作
    
    long long res=0;//该数出现的次数
    
    //这个for统计1~n中x出现的次数,在for循环的时候是让i为最高位开始计算x的次数
    //如548,则算的顺序:i=2(3-1),算0~9出现的次数,因为是高位没有前位,所以不用进入if算前位
    //                  i=1,    算0~9出现的次数,因为不是最高位,所以要进入if算前位。
    //                  i=0,     算0~9出现的次数,因为不是最高位,所以要进入if算前位。
    //这样就能算出每位上x出现的次数了,用res加每位出现的次数
    
    //这里-!x是指,若x==0则不用看最高位,因为一个数字最高位不可能为0
    for(int i=n-1-!x;i>=0;i--)//例:abcdefg,求d位为x的次数。此时的i为位数,从高到底,最高位为n-1号位,最低位为0号位
    {
        //一:d位之前的三位小于abc时(总位数小于数字的位数时+总位数等于数字的位数且前三位小于abc时):000~abc-1,d位出现的次数为abc*10^efg,即abc*1000
        if(ix
        //1:dx,则后面三位可以是000~999,一共1000次
        else if(num[i]>x) res+=power10(i);
    }
    return res;
}

int main()
{
    int a,b;
    scanf("%d%d",&a,&b);
    while(a||b)//题目要求ab同时为0时终止
    {
        if(a>b)swap(a,b);//保持b>a

        for(int i=0;i<10;i++)
           printf("%lld ",count(b,i)-count(a-1,i));//算a~b中的每个数字中i出现的次数
        printf("\n");
        
        scanf("%d%d",&a,&b);
    }
    return 0;
}

你可能感兴趣的:(算法基础,动态规划,算法)