[COGS193]最多因子数 解题报告

本文介绍了如何通过优化搜索顺序和应用剪枝策略解决一个寻找区间内因子数最多整数的难题。首先,通过枚举质因子避免重复计算,然后使用最优化剪枝和合法性剪枝提高效率。此外,讨论了骗分策略,包括针对特殊数据的暴力解法和处理大质数的优化。
摘要由CSDN通过智能技术生成

这真是一道很神的题,看起来似乎只能暴搜,但是暴搜的话又没法解决出现了大质数因子的问题,所以我蛋疼了一下午还是写了个骗分+暴力,但没想到竟然A了!

后来我看了题解,感到很不满意,因为题解根本就没有处理存在大质数的问题。

让我们先来看看所谓的正解:

    本题的要求是,求出一个给定区间内的含因子数最多的整数。

    首先,有必要明确一下如何求一个数的因子数。若一个数N满足N=P1N1·P2N2·P3N3·…·PmNm,其中P1, P2, , Pm是Nm个质因子。则N的约数个数为(N1+1)·(N2+1)·(N3+1)·…·(Nm+1)。这一公式可以通过乘法原理来证明。

    有了求因子数的公式后,最容易想到的算法就是,枚举区间内的每个整数,统计它们的约数个数。这个算法很容易实现,但是时间复杂度却相当高。因为区间中整数的范围是11000000000,整个枚举一遍并计算因子数的代价约为109×(109)0.5=1013.5。这个规模是无法忍受的。所以,我们需要尽量优化时间。

    分析一下枚举的过程就会发现,如果我们分别枚举两个数np·np为一相对较大的质数),那么我们将重复计算两次n的因子数。其实,如果枚举顺序得当的话,完全可以在n的基础上去计算p·n,而如果能在n的基础上计算p·n,就相当于计算p·n的因子数只用了O(1)的时间。这是一个比较形象的例子,类似的(可能相对更复杂一些)重复计算在枚举过程中应该是普遍存在的。这就是枚举效率低的根本所在。为了解决这一重复,我们可以选取另一种搜索顺序——枚举质因子。这样的搜索顺序可以避免前面所说了类似np·n的重复计算。

    定义number为当前搜索到的数。初始时,令number=1,然后从最小的质数2开始枚举,枚举因子中包含021222、…、k2的情况……直至number·2k大于区间的上限(max)。对于每个“2k的情况”,令number:=number*2k,在这个基础上,再枚举因子3索的过程,搜索的过程中,利用前面提到的求因子数的公式可以算出当前的number的因子数供下一层枚举继承。当number大于等于区间下限(min)时,我们就找到了一个区间内的数(枚举的过程已保证number不超过上界)。所有枚举得到的区间内的数中,因子数的最大值就是我们要求的目标。

    这样的枚举完全去除了重复计算,但是这还是不够的,因为光11000000000内的数每枚举一遍就有109个单位的操作。所以,我们还需要找到一些剪枝的方法,进一步优化时间。

    我们看到,如果当前搜索状态为(from, number, total),其中,from是指当前枚举到的质因子(按从小到大枚举),total是指number中包含的因子数。那么剩下的因子数最多为q=logfrommax/number,这些因子组成的因子个数最大为2q。因此,当前所能取到的(理想情况)最大约数个数就是total·2q。如果这个数仍然无法超过当前最优解,则这一分支不可能产生最优解,可以剪去。

    此外,如果[(min-1)/number]=[max/number],则表示以当前状态搜索下去,结果肯定不在区间内了,就无法产生合法解,也可剪去。不过,这一剪枝作用不是很大,因为即使不剪,再搜索一层也就退出了。

    以上两个剪枝,前一个是最优化剪枝,后一个是合法性剪枝。相比较而言,前一个剪枝的作用要大得多。

    下面我们用平摊分析的方法来讨论一下搜索的复杂度。由于枚举的过程中没有重复计算,每枚举一个质因子,都可以得到一个不同的number(number

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值