BZOJ 1833 count 数字计数 数位DP

本文介绍了一种使用数位动态规划(数位DP)解决特定类型数学问题的方法。通过两个正整数a和b,计算区间[a,b]内所有整数中每个数码出现的次数。文章提供了一个C++实现案例,详细展示了如何利用数位DP技巧进行有效计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【Description】
给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次。
【Input】
输入文件中仅包含一行两个整数a、b,含义如上所述。
【Output】
输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次。
【解题报告】
这道题很容易看出是一个数位dp。其技巧主要在于判定以及输出空格、回车符上。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long a,b;
long long ans[10],f[20];
void res(long long x,long long pos)  
{  
    while(x)  
        ans[x%10]+=pos,x/=10;  
}
void dp(long long x,int flag)
{
    long long pos,now;
    int i,j;
    for(i=1,pos=10;pos<x;++i,pos*=10)
    {
        for(j=0;j<=9;j++)
        ans[j]+=f[i-1]*9*flag;
        for(j=1;j<=9;j++)
        ans[j]+=pos/10*flag;
    }
    now=pos/=10;--i;
    while(now<x)
    {
        while(now+pos<=x)
        {
            long long temp=now/pos;
            res(temp,pos*flag);
            for(j=0;j<=9;j++)
            ans[j]+=f[i]*flag;
            now+=pos;
        }
        pos/=10;--i;
    }
}
int main()
{
    long long pos;
    int i,j;
    f[1]=1;
    for(i=2,pos=10;i<=12;i++,pos*=10)
    f[i]=f[i-1]*10+pos;
    scanf("%lld%lld",&a,&b);
    dp(b+1,1);
    dp(a,-1);
    for(j=0;j<=9;j++)
    printf("%lld%c",ans[j],j==9?'\n':' ');
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值