我在Google Code Jam中阅读了a problem about bullseyes。 (比赛结束了,所以可以谈论它)
玛丽亚以t毫升的黑色涂料开始,她将用它来画出厚度为1厘米(1厘米)的戒指。厚度为1cm的环是两个同心圆之间的空间,半径相差1cm。
玛丽亚在半径为r cm的白色圆圈周围画出第一个黑色圆环。
半径为1cm的圆盘面积为πcm2。需要1毫升涂料来覆盖面积π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=308436464205151562
和t=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
答案 0 :(得分:1)
对于符号精确操作,有sympy。
如果您粘贴以下内容:
a, b, c = 2, 616872928410303123, -1850618785230909388
x = Symbol('x')
int(max(solve(a*x**2 + b*x + c, x)))
here,你得到3。
[OP评论后编辑]。
答案 1 :(得分:1)
舍入精度使我在这个问题上遇到了麻烦......但你可以将所有内容保持在64位整数精度,并对得到的二次方程进行二分搜索。我概述了我的方法here。
答案 2 :(得分:0)
如果(t / r^2) > 10000
通过sqrt
计算
如果(t / r^2) < 10000
尝试每个n
从0开始增加1。
答案 3 :(得分:0)
使用@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)