count 数字计数 (数位dp)

给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次。
Input
输入文件中仅包含一行两个整数a、b,含义如上所述。
Output
输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次。
Sample Input
1 99
Sample Output
9 20 20 20 20 20 20 20 20 20
Hint

30%的数据中,a<=b<=10^6;
100%的数据中,a<=b<=10^12。


题目大概:

题目很精简。

思路:

做一个结构题存储所有的0到9的数的个数,并储存现在位的个数。

每次统计是把现在位的个数储存,并把以前存储的数字的数量一起进行赋值。

这个题主要是统计10位数,麻烦一点。


代码:


#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
int a[22];
 struct DP
{
    ll wei[10],sum;
    DP(){memset(wei,0,sizeof(wei));}
    DP(ll su):sum(su){memset(wei,0,sizeof(wei));}
}dp[20][2],ans[2];

DP sove(int pos,int lead,int limit)
{

    if(pos==-1)return DP(1);
    if(!limit&&~dp[pos][lead].sum)return dp[pos][lead];
    int end=limit?a[pos]:9;
    DP now(0);
    for(int i=0;i<=end;i++)
    {

        DP t=sove(pos-1,lead&&!i,limit&&i==a[pos]);
        for(int j=0;j<10;j++)
        {
            now.wei[j]+=t.wei[j];

        }
            now.sum+=t.sum;
            if(!lead||lead&&i)now.wei[i]+=t.sum;

    }

    if(!limit)dp[pos][lead]=now;

    return now;
}

void go(ll x,int k)
{
    int pos=0;
    while(x)
    {
        a[pos++]=x%10;
        x/=10;
    }
    ans[k]=sove(pos-1,1,1);
}
int main()
{
        ll m,n;

        for(int i=0;i<20;i++)
        {
            for(int j=0;j<=1;j++)
            {
                dp[i][j].sum=-1;
            }
        }
        while(cin>>m>>n)
        {

       memset(ans,0,sizeof(ans));
        go(n,0);
        go(m-1,1);

        for(int i=0;i<=9;i++)
        {
           if(i!=9)printf("%lld ",ans[0].wei[i]-ans[1].wei[i]);
            else printf("%lld\n",ans[0].wei[i]-ans[1].wei[i]);

        }

        }


    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值