AcWing 338. 计数问题

文章讲述了如何使用前缀和的思想解决AcWing338题目的计数问题。通过定义count函数计算1到n中数字i出现的次数,方法是累加不同位数上i出现的次数。在main函数中,对输入的a和b区间进行处理,输出区间内每个数字的计数差值。

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

338. 计数问题 - AcWing题库

AcWing 338. 计数问题<超短写法> - AcWing 题解看这篇即可

答题思路是首先采用前缀和的思想,我们需要求区间a到b上的,我们转化成1 - b上的减去1 - a - 1上的。

之后我们设计count(int n,int i)函数,用于求解1 - n上数字i出现的次数:

而实现这个函数具体功能,我们就巧妙地通过求解最大的数字n上的每一位i出现的次数,也即1 - n中所有数字的第一位是i的个数、1 - n中所有数字的第二位是i的个数、1 - n中所有数字的第三位是i等等,加在一起。就能得到count函数的返回值了。

#include<iostream>
#include<cmath>
#include<algorithm>

using namespace std;

int get(int n) {
    //该函数用于获得一个数的数位
    int res = 0;
    while(n) res++,n /= 10;
    return res;
}

int count(int n,int i) //n为1-n数的范围,i表示1-n数中数字i出现的次数
{
    int res = 0, nums = get(n);
    //表示
    for(int j = 1;j <= nums;j ++ ) {
        //首先是0-abc-1部分
        int p = pow(10,nums - j), l = n / p / 10, r = n % p, dj = n / p % 10;
        
        if(i) res += l * p;
        else res += (l - 1) * p;
        
        if(dj == i) res += r + 1;
        if(dj > i) res += p;
    }
    return res;
}
int main() 
{
    int a,b;
    while(cin>>a>>b,a) {
        //输入的a有可能大于b
        if(a>b) swap(a,b);
        for(int i = 0;i <= 9;i ++ ) cout<<count(b,i)-count(a - 1,i)<<" ";
        cout<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值