【问题标题】:Maximising a divisor of an array of values and summing the quotients最大化值数组的除数并对商求和
【发布时间】:2020-10-20 13:05:21
【问题描述】:

给定一个长度为N 的整数值数组P,我想最大化一个值M,其中P 的所有值都除以M 并求和到变量K ,但其中K 大于或等于值D

以下约束成立:

  • 1 ≤ N ≤ 10,000
  • 1 ≤ P[i] ≤ 1,000,000,000
  • 1 ≤ D ≤ 10,000,000
  • 1≤M≤10,000,000

例如,

D = 6, P = [10,11,14,15] and where M starts at 4:
sum([10,11,14,15] / 4) = sum([2,2,3,3]) = 10 # (D <= 10)
sum([10,11,14,15] / 5) = sum([2,2,2,3]) = 9 # (D <= 9)
sum([10,11,14,15] / 6) = sum([1,1,2,2]) = 6 # (D <= 6)
sum([10,11,14,15] / 7) = sum([1,1,2,2]) = 6 * # (D <= 6)
sum([10,11,14,15] / 8) = sum([1,1,1,1]) = 4 # (D > 4) -> break

*M 最大化,总和 K 保持大于或等于 D。

我做了以下但想找到一种不是蛮力的方法:

long Split(long[] P,int D){


    long K = Long.MAX_VALUE;

    int M = P.length-1;


    while(K >= min_amount) {


        M++;
        K = 0;

        for (long value : P)
            K += value/M;

    }


    return M-1;

}

}

【问题讨论】:

  • 如果 M = P.length-1 那么为什么在您的示例中将 M 设置为 5M最初是如何选择的?
  • 利用所有元素的总和除以 M 将始终大于或等于向下除数的总和这一事实,您可以通过将所有元素的总和除以 D 来得出 M 的上限然后在 1 作为下限和计算出的数字作为上限之间对 M 执行二进制搜索。虽然这可能不是完美的解决方案,但它会大大提高运行时间。
  • @MDK 感谢您的回复。你能详细说明二分搜索吗?我会在计算范围内搜索 M 的最大值吗?
  • 由于您需要对这些值求和,因此您似乎可以使用 LinkedList 并有选择地删除除数较大的值,因为商将为 0 并且不会影响其中的总和或未来的迭代。对于value &lt; divisor + divisor,您只需添加 1。
  • 我很抱歉没有完全理解这一点,但请考虑 P = [5,7,1,5,2,1,4,5,8,2,3] 如果 MP.length-1 那么总和为 0 并且迭代停止任何正值 D &gt; 0。我没有答案,但需要根据数组内容的一些初始数学特征和目标 D 智能选择 M

标签: java optimization dynamic-programming


【解决方案1】:

改善运行时间的一种相当简单的方法是使用数字的一些数学属性来缩小搜索区间。

S 是数组P 的所有元素的总和,让Mmax 是我们正在寻找的MKoptKMmax 计算的。然后我们可以声明

S/Mmax &gt;= Kopt &gt;= D因为地板只能减少K。所以S/D &gt;= Mmax

使用此界限,您可以在1S/D 之间对实际的Mmax 执行二分搜索。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-08
    • 1970-01-01
    • 1970-01-01
    • 2020-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多