初始给定一个长度为N的数组A,以及数组内数字大小的限制M,还有一个值K。<br>要求一次性选取i个元素合并为他们的gcd,使得数值的损失最少(即最终结果的各数字之和最大),对所有的i<=K求解<br>
M为1e6的简单版本
考虑枚举合并后gcd的值,那么被选取的一定是被gcd整除的最小的若干个数
对于每次枚举的值d,只需要从小到大判断每一个d的倍数是否出现,单次复杂度为O(m/d)
根据调和级数,可以做到总时间复杂度为O(mlogm)的求解
M为9e18的困难版本
由于值域较大,不能直接枚举gcd
考虑到当gcd确定时,是直接选最小的若干个数
如果直接选最小的若干个数为什么不行?<br>
直接选可能会导致gcd的值下降非常多,使得答案不优<br>
也就是说如果gcd的值下降不多,可以选择不操作一些大的数,改成较小的数进行操作
考虑对一个已经确定的方案进行调整,得出更优解
删除当前已选数中最大的数,并加入能加进来的最小的数,计算收益
计算发现,如果加进来的数字比之前的次小值小,那么加入与删除的两个数的数值之差一定大于之前的gcd,这样答案就会更优。因为这时减少删数带来的收益足够大,可令gcd的损失能忽略不计
得出结论:最优解中最小的i-1个数字一定是原数组中最小的i-1个数字
得出做法:每次选最小的i-1个数,并考虑最后一个数字选哪个更优
对每个i进行枚举会超时
分析子问题:每次相当于有当前已知的gcd值x,要选一个数字y使得y-gcd(x,y)最小<br>
对应的x实际上就是前缀gcd,那么有一个经典性质:前缀gcd的值的个数为O(log)级别的<br>
对每个不同的前缀gcd进行求解,那么复杂度就是O(nlog^2m)的<br>