分治算法——我现在的认为是将一个复杂的难以有明显解题思路的问题——依据其问题性质与特殊点拆分为几个性质相同的(易于实现的)小问题——为解决这些小问题只需要定义同一个函数——从而分而治之解决这个大问题
第一个遇见的实例是页码问题,我目前水平有限对这个算法的理解难免有所局限,我会及时更改理解错误的地方。也欢迎大家多多批评指教!
对于书页问题我的思路就是硬解,没有去寻找他们之间的通用点,直接去硬解,结果只能是打出一堆垃圾代码,然后一直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)
//水平有限,不能清晰的展现出我的思路,请您见谅,我会时常精简这篇的文字~~