【问题标题】:How to exactly solve quadratic equations with large integer coefficients (over integers)?如何精确求解具有大整数系数(超过整数)的二次方程?
【发布时间】:2013-04-21 13:55:35
【问题描述】:

我在 Google Code Jam 中读到了a problem about bullseyes。 (比赛已经结束了,聊聊就好了)

Maria 从 t 毫升黑色颜料开始,她将用它来绘制厚度为 1 厘米(一厘米)的环。 1cm厚的圆环是两个半径相差1cm的同心圆之间的距离。

Maria 在半径为 r cm 的白色圆圈周围画出第一个黑色环。

半径为 1cm 的圆盘面积为 π cm2。覆盖面积 π cm2 需要一毫升油漆。玛丽亚最多可以画出多少个黑环?

根据我在纸上的计算,绘制具有 n 个环、内半径 r 的靶心的油漆面积是 pi 的倍数是2*n**2 + n*(2*r-1)

所以给定t*pi 毫升的油漆,问题是找到最大的n,使得f(n,r) <= t

今天早上我用二分搜索解决了这个问题https://github.com/hickford/codejam/blob/master/2013/1A/bullseye/bullseye.py

我选择二分搜索而不是二次方程,因为我非常担心浮点不精确——在这个问题中,t 和 r 是 10**18 大的整数)。在之前的 Code Jam 中,算术不精确让我印象深刻。

但我很好奇。你能支持二次方程以给出具有大整数系数的方程的正确答案吗?像 Sympy 或 Numpy 这样的数学库有什么可以提供给我的吗?


证明二次方程对大输入给出了错误的答案。例如,r=308436464205151562t=1850618785230909388 。求解的二次方程为

2*n**2 + 616872928410303123*n -1850618785230909388 <= 0

即。系数是

a = 2
b = 616872928410303123
c = -1850618785230909388

用 Python 计算

    > int((-b + math.sqrt(b**2 - 4*a*c)) / (2*a))
    0

这是错误的答案!正确答案(通过二分搜索找到)是 3

>>> n = 3
>>> 2*n**2 + 616872928410303123*n -1850618785230909388 <= 0
True

【问题讨论】:

  • 不就是用二次方程吗?
  • 在之前的一次code jam中,我被一个浮点精度错误stackoverflow.com/q/15978781/284795
  • 在这么小的整数上使用 math.sqrt 应该没有任何问题。
  • @VaughnCato,上面添加了反例。
  • 得到整数 sqrt 后,减去整数 b 即可得到整数 x。然后你只需要确定x/4 向下舍入为一个整数。 int(x/4) = int(int(x)/4).

标签: python algorithm math equation-solving


【解决方案1】:

对于符号精确操作,有sympy

如果您粘贴以下内容:

a, b, c = 2, 616872928410303123, -1850618785230909388
x = Symbol('x')
int(max(solve(a*x**2 + b*x + c, x)))

here,你得到 3。

[在 OP 评论之后编辑]。

【讨论】:

  • 更像 3.0? int(max(solve(a*x**2 + b*x + c, x))) 返回 3,这是正确的答案。谢谢!整洁的 REPL
【解决方案2】:

如果(t / r^2) &gt; 10000 通过sqrt 计算。
如果(t / r^2) &lt; 10000 尝试每个n 从0 开始增加1。

【讨论】:

    【解决方案3】:

    @Vaughn 建议的使用整数平方根的解决方案

    def solve2(r,t):
        """Maximum number of black rings that Maria can draw, with inner radius r, given pi*t of paint. Solve using quadratic equation"""
        import gmpy
        from gmpy import mpz
    
        a = 2
        b = 2*r - 1
        c = -t
    
        x = (-b + mpz(b**2 - 4*a*c).sqrt()) // (2*a) 
        return int(x)
    

    【讨论】:

      【解决方案4】:

      舍入精度让我在这个问题上死了...但是您可以将所有内容保持在 64 位整数精度,并对得到的二次方程进行二进制搜索。我概述了我的方法here

      【讨论】:

        猜你喜欢
        • 2013-12-13
        • 2015-11-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-04
        相关资源
        最近更新 更多