51nod 1042 数字0-9的数量(数位dp)

本文介绍了一种算法,用于计算一个给定范围内特定数字出现的总次数,特别是处理前导0的情况。通过动态规划的方法预计算部分结果,并利用递归思想解决一般情况。

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

做法同51nod 1009 数字1的数量 相差不多,不过查询0的时候要特别处理,做的时候拿别人代码调了好久才看懂。。。参考的:http://blog.youkuaiyun.com/f_zyj/article/details/52082449

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;

ll dp[20];

void init()
{
    //如果算前导0,0-9都是一样的次数,,不过不算前导0,所以后边0要单独处理
    for(int i = 1; i <= 18; ++i)
        dp[i] = dp[i-1]*10 + pow(10,i-1);
}

ll solve(ll num, ll aim)
{
    ll len = 0;
    ll ten = 1;
    ll res = 0;
    ll tail = 0;
    ll temp = num;
    ll cur;
    while(temp)
    {
        cur = temp%10;
        temp /= 10;
        ++len;

        if(cur > aim)
        {
            //cur*dp[len-1]是当前位低一位为aim的情况,ten是当前位为aim的情况
            res = res + cur*dp[len-1] + ten;
        }
        else if(cur == aim)
        {
            //因为cur==aim,所以不能直接加ten,所以要加tail,例如aim=1,这就是101~到1xx的百位为aim的情况,+1是指100
            res = res + dp[len-1] + 1 + tail;
        }
        else
        {
            //这里同cur > aim差不多,只是没有当前位为aim的情况
            res = res + cur*dp[len-1];
        }
        //现在记录的tail就是下一轮循环中当cur==aim时的aim000-aimxxx的最高位为aim的情况
        tail = tail + cur*ten;
        ten *= 10;
    }
    //处理0
    if(!aim)
    {
        ll cnt = 1;
        while(num)
        {
            res -= cnt;
            cnt *= 10;
            num /= 10;
        }
    }
    return res;
}

int main()
{
    init();
    ios::sync_with_stdio(false);
    ll a,b;
    cin >> a >> b;
    for(int i = 0; i < 10; ++i)
    {
        cout << solve(b,i) - solve(a-1,i) << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值