分治算法实践——书页!


分治算法——我现在的认为是将一个复杂的难以有明显解题思路的问题——依据其问题性质与特殊点拆分为几个性质相同的(易于实现的)小问题——为解决这些小问题只需要定义同一个函数——从而分而治之解决这个大问题

第一个遇见的实例是页码问题,我目前水平有限对这个算法的理解难免有所局限,我会及时更改理解错误的地方。也欢迎大家多多批评指教!


对于书页问题我的思路就是硬解,没有去寻找他们之间的通用点,直接去硬解,结果只能是打出一堆垃圾代码,然后一直WA到头大!!


Description
要期末考试了,陶陶在看书复习,看着看着就走神了,他注意到书的每页都一个页码,而且页码都是阿拉伯数字,于是他就想知道一个很纠结的问题,就是从1到N页,阿拉伯数字1一共出现多少次。
Input
输入只有一行一个整数N(1<=N<=50000)
Output
输入阿拉伯数字1出现的次数
Sample Input
30
Sample Output
13

这个题是输入a,b求a-b中1出现次数的简化版,其实已经分治为两个子问题了——a-b分解为0-b和0-a,分别求出1出现的次数b1于a1,最后得出a-b中1出现的次数为b1-a1

(当然边界是否能取也是一个考察)


那怎么求0-a中1出现的次数呢(其实解决了这个问题就相当于解决了1-9出现的次数了,当然0出现的次数还得多考虑一点)

一下代码讲解的是求0-9出现的次数方法——输出为1出现的次数


以三位数123为例:这个数可以分为120+3就是把‘个位’数与其它位数分开——很明显个位不完整应当分开考虑——这样就可以把这个不完整个位所带来的次数影响解决掉了

——那么我们可不可以都这么解决呢——如果可以那就真的省了很多事——这么偌大复杂的问题——就变成了最低位对其它位的影响问题


120很明显可以看成12*10,除以10就变成12——多出了一个不完整‘个位‘2——但是2原本是十位——所以就得定义一个权值——每一次更新个位权值都得乘以10——并且计算过程中要注意引入权值

如下代码n位页数,求0-n中1出现的次数——one存储’个位(散位)‘ten  存储’个位外的位(完整位)‘

第一个for循环——把个位(散位)出现的次数统计——注意权值有关(初始为1)

while循环——统计的是个位(散位)对完整位的影响——每一个完整位中的最大数((下方有解释)如120就是1和2,982就是9和8,2分别让9和8多出现3次【别忘了0,,统计应为0-9】)的出现次数都受个位(散位)长度的影响——时间一下不难得出【个位+1(数字0)】*权值这一个影响值

但ten%10是什么意思呢,还是以123为例ten是12,ten%10=2——得出个位对完整位0的影响,ten/10=1——下一轮ten=1,ten%10=1,ten/10=0——下一轮,ten=0,——结束,你会发现,这个循环加和的数是2和1——ten%10,ten/10就遍历了所有的’十位‘

那换一下ten=19会怎么样你会发现扫描的是9和1,那ten=29那么扫描的就是9和2,你就会发现,这个while循环计算的是当前个位(散位)对后续每一位的数字的影响(为什么额外进行这个统计应为这一部分的影响与个位(散位)数的大小有关)剩下的都是整算了。

之后再来一个for循环计算的值与ten有关而ten表示的是剔除个位并除以10的情况也就是其它位的出现次数——ten=12肯定会有12个整位1,ten=9肯定0-9都会出现9次(在整位上),这些出现的次数均与n有关,当然与权值也有关

这样之后,进行的步骤相当于把个位左移一位,其它位左移一位,再次进行重复判断,因为每一次都会更新出非完整位,都会有额外的次数加入


总结一下:1234|5把一个数这么分开(左边为整位,整位最前以为4为十位右边为散位),先把5内出现的1,2,3,4,5,0统计,然后这五个数都对后续位数出现的次数造成了影响——即1,2,3,4均因为散位多出现了5+1次,做好统计,剩下的就是所有整位的统计——额外的出现次数是1234——统计的是最外侧的数据。一位数的最内侧0-9,二位数的的最内侧0-9,……

这样你会发现这一次函数循环就把散位统计ok(现是表面(如123的0-3)再就是内部如123——3所在位的所有数【0不能算,所以得减一】)

在下次循环,散位和十位左移,直到最后完成统计~!

为什么以n-1作为下一次循环的初始值,因为散位的计算所需比如12,2本身就不在整,因为前一个散位已经将2计算完毕,2已经不能再进行散的统计了。末尾的一位必须减一,才可以不导致重复……、

(PS)第15行有个错误,can you find it???




小结一下我理解的思路——

首先把大数分开-----|-;分为完整位|散位

然后开始进行第一次的循环——先单独统计散位的页数——在后统计散位对完整位最大数字的影响(因为这个影响导致完整位不可以进行整数统计,做完这个统计之后就可以,就可以进行规律统计了)——在后就是对最内侧的所有数的统计

这一次循环后——散位统计完毕——散位的影响统计完毕——下一波循环散位迁移,再次统计散位(权值*10)


//水平有限,不能清晰的展现出我的思路,请您见谅,我会时常精简这篇的文字~~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值