给出四个正整数numpy.searchsorted
,,和,有没有办法快速找到任意两个整数和{{3这样:
当和时,使用二次方程有一个封闭形式的解决方案。我们只需找到的根,它就会给我们一个合适的。
时,我知道如何在中通过注意到曲线是凸的来解决它,因此我们可以二元搜索合适的。
时,可以通过对因子进行分解,并寻找一对与该范围内的值相加的因子来解决。
然而,当它们都是范围时,我无法想到任何可以有效解决这个问题的算法。有一些可能的启发式方法,比如修复两个中的一个(迭代较小的范围等),或者当可以使用两个整数求和为的最大可能产品时,立即报告不存在对。小于等
不幸的是,我还没有能够提出任何能够在一般情况下工作的东西,而不是迭代或中的所有东西(可能还有一些额外的东西)较小的因素)。是否有一个很好的算法,或一些花哨的数学,可以提供更快的解决方案?
或者,有没有办法证明迭代会很快终止? (在处理了一些角落案件等之后)我对有效对的数量不感兴趣;找到任何一对都会。如果允许总和的范围足够大,似乎迭代产品并试图找到相应的和趋向于快速找到解决方案。可以有某种证据吗?
我非常感谢任何帮助!
答案 0 :(得分:3)
您可以在O(sqrt(P2))时间内解决它。
找到这些总和:small_sum = i + ceiling(P1 / i)和big_sum = i + floor(P2 / i),i介于1和sqrt(P2)之间。
如果是small_sum> big_sum或big_sum< s1或small_sum> s2然后我不是解决方案的一部分。继续前进。
否则,max(small_sum,s1)min(big_sum,s2),以及“good sums”之间的所有值。对于其中任何一个,让j = good_sum - i。然后i + j是s1和s2之间的值,i * j在p1和p2之间。
我们最多检查i的sqrt(P2)值,并且对于这些值中的每一个,我们都在不断地工作。
编辑 - Ruby实现
def solve(s1, s2, p1, p2)
max_i = (p2**0.5).floor
1.upto(max_i) do |i|
small_sum = i + (p1/i.to_f).ceil
big_sum = i + (p2/i.to_f).floor
next if big_sum < s1 || small_sum > s2 || big_sum < small_sum
good_sum = [small_sum, s1].max
puts "sum: #{i} + #{good_sum - i} = #{good_sum}, #{s1} <= #{good_sum} <= #{s2}"
puts "product: #{i} * #{good_sum-i} = #{i*(good_sum-i)}, #{p1} <= #{i*(good_sum-i)} <= #{p2}"
return
end
puts "no solution"
end