AcWing 338. 计数问题(数位统计dp)

                                                      

                                   AcWing 338. 计数问题

给定两个整数 a 和 b,求 a 和 b 之间的所有数字中0~9的出现次数。

例如,a=1024,b=1032,则 a 和 b 之间共有9个数如下:

1024 1025 1026 1027 1028 1029 1030 1031 1032

其中‘0’出现10次,‘1’出现10次,‘2’出现7次,‘3’出现3次等等…

输入格式

输入包含多组测试数据。

每组测试数据占一行,包含两个整数 a 和 b。

当读入一行为0 0时,表示输入终止,且该行不作处理。

输出格式

每组数据输出一个结果,每个结果占一行。

每个结果包含十个用空格隔开的数字,第一个数字表示‘0’出现的次数,第二个数字表示‘1’出现的次数,以此类推。

数据范围

0

#include
using namespace std;
int a,b;

    // 类似与前缀和的思想,用count(n,i)来表示在1到n之中数字i出现的次数
    // 用count(b,i)-count(a-1,i) 来求解a到b之间i出现的次数
    //     对于任意一个数我们
    //     用dj表示第j位数
    //     用l表示j之前的数
    //     用r表示j后面的数
    //     用p表示从0到j共多少个数
    //     例如7位数abcdefg,当j=4时
    //     dj=d  l=abc  r=efg   p=1000
    // 我们用xxx i jjj来表示在1到n之间的数
    // res表示方案数,则有以下4种情况
    // 1   i=0   l!=0
    //             1.1  1<=xxx<=l-1     
    //                                     res=(l-1)*p
    //             1.2  xxx=l
    //                     1.2.1   idi    res=0
    // 2   i!=0  l=0
    //             同1.2

    // 3   i!=0  l!=0
    //             3.1  000<=xxx<=l-1      res=l*p
    //             3.2  xxx=l
    //                     同1.2

    // 4   i=0   l=0
    //             不存在


int div(int n)
{
    int res=0;
    while(n)
    {
        res++;
        n/=10;
    }
    return res;
}

int count(int n,int i)
{
    int res=0,len=div(n);
    for(int j=1;j<=len;j++)
    {
        int p=pow(10,j-1);
        int r=n%p;
        int l=n/p/10;
        int dj=n/p%10;

        if(i==0&&l!=0)
            res+=(l-1)*p;
        if(i!=0&&l!=0)
            res+=l*p;
        if((dj>i)&&(i||l))
            res+=p;
        if((dj==i)&&(i||l))
            res+=r+1;
    }
    return res;
}

int main()
{
    while(cin>>a>>b,a&&b)
    {
        if(a>b)
            swap(a,b);
        for(int i=0;i<10;i++)
            cout<

你可能感兴趣的:(AcWing 338. 计数问题(数位统计dp))