Czytam a problem about bullseyes w Google Code Jam. (Konkurs się skończył, więc jest w porządku, aby o tym mówić)Jak dokładnie rozwiązać równania kwadratowe o dużych współczynnikach całkowitych (w liczbach całkowitych)?
Maria rozpoczyna się t mililitrów czarną farbą, która będzie używała wyciągnąć pierścienie 1cm grubości (jeden centymetr). Pierścień o grubości 1 cm to przestrzeń między dwoma współśrodkowymi okręgami, których promienie różnią się o 1 cm.
Maria rysuje pierwszy czarny pierścień wokół białego okręgu o promieniu r cm.
Obszar dysku o promieniu 1 cm to π cm2. Do pokrycia powierzchni π cm2 wymagane jest 1 mililitr farby. Jaka jest maksymalna liczba czarnych pierścieni, które Maria może narysować?
Według moich obliczeń na papierze, powierzchnia farby narysować dziesiątkę zn pierścienie, wewnętrzny promień r, jako wielokrotność PI 2*n**2 + n*(2*r-1)
Więc podane t*pi
millitres farby problemem jest znalezienie największy n taki, że f(n,r) <= t
.
Dziś rano rozwiązany, że przy wyszukiwaniu binarnym https://github.com/hickford/codejam/blob/master/2013/1A/bullseye/bullseye.py
Wybrałem przeszukiwanie binarne nad równania kwadratowego, bo jestem bardzo ostrożny zmiennoprzecinkowej nieścisłości - w ten problem t i R są liczbami całkowitymi wielkie jak 10 ** 18). Niedokładność arytmetyczna ugryzła mnie w poprzednim Zakleszczeniu kodu.
Ale jestem ciekawy. Czy możesz wzmocnić równanie kwadratowe, aby dać poprawną odpowiedź dla równań o dużych współczynnikach całkowitych? Czy biblioteki matematyczne takie jak Sympy czy Numpy mają coś do zaoferowania?
Demonstracja, że równanie kwadratowe daje błędną odpowiedź dla dużych wejść. Na przykład z r=308436464205151562
i t=1850618785230909388
. Równanie kwadratowe do rozwiązania to:
2*n**2 + 616872928410303123*n -1850618785230909388 <= 0
tj. współczynniki są
a = 2
b = 616872928410303123
c = -1850618785230909388
Computing w Pythonie
> int((-b + math.sqrt(b**2 - 4*a*c))/(2*a))
0
To zła odpowiedź! Prawidłowa odpowiedź (znaleziona za pomocą wyszukiwania binarnego) to 3
>>> n = 3
>>> 2*n**2 + 616872928410303123*n -1850618785230909388 <= 0
True
Czy nie używasz równania kwadratowego? –
W poprzednim zacięciu kodu, zostałem ugryziony przez błąd precyzji zmiennoprzecinkowej http://stackoverflow.com/q/15978781/284795 –
Nie powinieneś mieć żadnego problemu z użyciem math.sqrt na liczbie całkowitej, która jest mała. –