给定范围内的总和和乘积

时间:2017-07-05 19:38:45

标签: algorithm math

给出四个正整数numpy.searchsortedS_1S_2P_1,有没有办法快速找到任意两个整数P_2和{{3这样:

  • a
  • b

S_1 \leq a+b \leq S_2P_1 \leq ab \leq P_2时,使用二次方程有一个封闭形式的S_1 = S_2解决方案。我们只需找到P_1 = P_2的根,它就会给我们一个合适的O(1)

a^2 - S_1*a + P_1时,我知道如何在a中通过注意到S_1 = S_2曲线是凸的来解决它,因此我们可以二元搜索合适的O(log S_1)

f(a) = a(S_1 - a)时,a可以通过对因子P_1 = P_2进行分解,并寻找一对与该范围内的值相加的因子来解决。

然而,当它们都是范围时,我无法想到任何可以有效解决这个问题的算法。有一些可能的启发式方法,比如修复两个中的一个(迭代较小的范围等),或者当可以使用两个整数求和为O(sqrt P_1)的最大可能产品时,立即报告不存在对。小于P_1

不幸的是,我还没有能够提出任何能够在一般情况下工作的东西,而不是迭代S_2P_1中的所有东西(可能还有一些额外的东西)较小的因素)。是否有一个很好的算法,或一些花哨的数学,可以提供更快的解决方案?

或者,有没有办法证明迭代会很快终止? (在处理了一些角落案件等之后)我对有效对的数量不感兴趣;找到任何一对都会。如果允许总和的范围足够大,似乎迭代产品并试图找到相应的和趋向于快速找到解决方案。可以有某种证据吗?

我非常感谢任何帮助!

1 个答案:

答案 0 :(得分:3)

您可以在O(sqrt(P2))时间内解决它。

  1. 找到这些总和:small_sum = i + ceiling(P1 / i)和big_sum = i + floor(P2 / i),i介于1和sqrt(P2)之间。

  2. 如果是small_sum> big_sum或big_sum< s1或small_sum> s2然后我不是解决方案的一部分。继续前进。

  3. 否则,max(small_sum,s1)min(big_sum,s2),以及“good sums”之间的所有值。对于其中任何一个,让j = good_sum - i。然后i + j是s1和s2之间的值,i * j在p1和p2之间。

  4. 我们最多检查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