PAT-A1049解题报告

本文介绍了一种高效算法,用于计算1到N范围内所有数字中数字1出现的总次数。通过将问题分解为按位计数,避免了直接枚举的大规模计算,特别适用于大数据量场景。

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

题目大致意思是要求出1~N中数出现的1的个数。有种很直接的办法就是枚举1~N中的数,统计每个数共有多少位出现1,最后把结果累加起来。但这种办法在数据量大时用时过长,我们可以换个角度思考,把会被记录到总数的1按照位进行划分,统计第i位为1的在1~N中数字的个数,把得到的结果累加起来,就能得到1~N中数出现的1的个数。

举例

N = 30710,从第一位开始统计每一位为1时数字的个数。

  1. 第一位为1时
    为了不超过N,第一位的前面四位可以取0000,0001,...,3070,如果取3071就会得到30711超过30710
  2. 第二位为1时
    此时第二位前的三个数可以取000,001,...,306,最后一位可以取任意的0~9中的数。
    当前三位取307时,最后一位就只能取0
  3. 第三位取1时
    此时前两位可以取00,01,...,30,而后两位可以取00,01,...,99
    以此类推

规律

设我们要讨论的数是N,讨论N的一位(用a表示,讨论下一位时就让a乘以10),该位为nowNnow左侧的部分大小为left,右侧部分为right,该位为1的数字个数为ans,满足等式:

  1. now = 0ans = left * a
  2. now = 1ans = left * a + right + 1
  3. now > 1ans = (left + 1) * a

实现

只要维护一个迭代过程中不断乘以10表示进一位的数aleft,now,right都可以通过除法和求余得到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值