最多约数问题 首先,有必要明确一下如何求一个数的因子数。若一个数满足,其中是的个质因子。则的约数个数为。这一公式可以通过乘法原理来证明。 有了求因子数的公式后,最容易想到的算法就是,枚举区间内的每个整数,统计它们的约数个数。这个算法很容易实现,但是时间复杂度却相当高。因为区间中整数的范围是,整个枚举一遍并计算因子数的代价约为(109×(109)0.5=1013.5)。这个规模是无法忍受的。所以,我们需要尽量优化时间。 分析一下枚举的过程就会发现,如果我们分别枚举两个数和(p为一相对较大的质数),那么我们将重复计算两次的因子数。其实,如果枚举顺序得当的话,完全可以在n的基础上去计算,而如果能在n的基础上计算,就相当于计算的因子数只用了的时间。这是一个比较形象的例子,类似的(可能相对更复杂一些)重复计算在枚举过程中应该是普遍存在的。这就是枚举效率低的根本所在。为了解决这一重复,我们可以选取另一种搜索顺序——枚举质因子。这样的搜索顺序可以避免前面所说了类似和的重复计算。 定义为当前搜索到的数。初始时,令,然后从最小的质数2开始枚举,枚举因子中包含的情况……直至大于区间的上限。对于每个“的情况”,令,在这个基础上,再枚举因子3的情况。然后在3的基础上枚举因子5的情况,然后是7的情况……整个过程是一个深度搜索的过程,搜索的过程中,利用前面提到的求因子数的公式可以算出当前的的因子数供下一层枚举继承。当大于等于区间下限时,我们就找到了一个区间内的数(枚举的过程已保证不超过上界)。所有枚举得到的区间内的数中,因子数的最大值就是我们要求的目标。
这样的枚举完全去除了重复计算,但是这还是不够的,因为光1~1000000000内的数每枚举一遍就有109个单位的操作。所以,我们还需要找到一些剪枝的方法,进一步优化时间。 我们看到,如果当前搜索状态为,其中,是指当前枚举到的质因子(按从小到大枚举),是指中包含的因子数。那么剩下的因子数最多为,这些因子组成的因子个数最大为。因此,当前所能取到的(理想情况)最大约数个数就是。如果这个数仍然无法超过当前最优解,则这一分支不可能产生最优解,可以剪去。 此外,如果,则表示以当前状态搜索下去,结果肯定不在区间内了,就无法产生合法解,也可剪去。不过,这一剪枝作用不是很大,因为即使不剪,再搜索一层也就退出了。 以上两个剪枝,前一个是最优化剪枝,后一个是合法性剪枝。相比较而言,前一个剪枝的作用要大得多。 下面我们用平摊分析的方法来讨论一下搜索的复杂度。由于枚举的过程中没有重复计算,每枚举一个质因子,都可以得到一个不同的,所以可以将每一个单位的枚举质因子的代价与一个不超过的对应,并且还可在两者之间建立双射。不同的最多只有个,所以枚举的总代价不超过。 加上了剪枝以后,计算总代价就远远小于了。从运行效果来看,即便是最大数据,也可以很快出解。 从本题的解决过程中可以看到,最关键的有两步: (1)采用合理的搜索顺序,避免重复计算; (2)利用最优化剪枝和合法性剪枝,剪去一些不可能产生最优解或合法解的分支。 这两种优化的方法在搜索中的地位是极其重要的,当然可能在本题中的重要性体现得格外突出。