今天小编给大家分享一下怎么用Python求解阿基米德分牛问题的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
题目大意
问 太阳神有一牛群,由白、黑、花、棕四种颜色的公、母牛组成,其间关系如下,求每种牛的个数。
公牛中,白牛多于棕牛,二者之差为黑牛的1/2+1/3;黑牛多于棕牛,二者之差为花牛的1/4+1/5;花牛多于棕牛,二者之差为白牛数的1/6+1/7
母牛中,白牛是全体黑牛的1/3+1/4;黑牛是全体花牛的1/4+1/5;花牛是全体棕牛的1/5+1/6;棕牛是全体白牛的1/6+1/7
如果用字母x0,x1, x2 , x3分别表示白、黑、花、棕各色的公牛数;用y0,y1,y2,y3分别表示白、黑、花、棕各色母牛数,则得8 个未知数的如下7 个方程
这个题其实是毫无难度的,但非要用Python,那么难点主要如何优雅地表达这个过程,这里选用的是sympy符号计算。
所以第一步,先给定一些符号
import sympy
x0,x1,x2,x3 = sympy.symbols("x0,x1,x2,x3")
y0,y1,y2,y3 = sympy.symbols("y0,y1,y2,y3")
x = [x0,x1,x2,x3]
y = [y0,y1,y2,y3]
sympy求解
然后将阿基米德分牛问题转化为Python代码,其优雅之处在于,这些分数的构建遵循自然数递增的规律,故可通过循环来生成,非常便捷。
frac = lambda x : sympy.Rational(1,x)
fs = []
for i in range(3):
fs.append(x[i]-x[3]-(frac(2*i+2)+frac(2*i+3))*x[i+1])
for i in range(4):
ind = (i + 1) % 4
fs.append(y[i]-(frac(i+3)+frac(i+4))*(x[ind]+y[ind]))
这样就得到了待求方程组
>>> for f in fs: print(f)
...
x0 - 5*x1/6 - x3
x1 - 9*x2/20 - x3
x2 - 55*x3/42
-7*x1/12 + y0 - 7*y1/12
-9*x2/20 + y1 - 9*y2/20
-11*x3/30 + y2 - 11*y3/30
-13*x0/42 - 13*y0/42 + y3
但是,8个未知数7个方程,显然没有唯一解,考虑到x3貌似是最小的值,所以最后希望用x3来表示其他数。
res = sympy.solve(fs, x[:3]+y)
结果
查看一下结果
for key in res:
print(sympy.latex(key), "&=", sympy.latex(res[key]), r"")
这道题到这里基本上就算解完了,但是牛至少得是个整数,所以接下来要做的是求解分母的最小公倍数。
在sympy中,对于一个分数r,r.p为分子,r.q为分母;lcm可求解其最小公倍数。
denominators = [(v/x3).q for v in res.values()]
x3Res = sympy.lcm(denominators)
# 32859792
然后让将x3的值加入fs,
fs.append(x3-x3Res)
res2 = sympy.solve(fs, x+y)
for key in res2:
print(sympy.latex(key), "=", res2[key], r"")
结果如下
x0=76379457
x1=52223598
x2=43030680
x3=32859792
y0=48646815
y1=31170942
y2=26238080
y3=38698608
这些牛加一起有349247972头,全世界大概有10万亿头,看来太阳神的牛还是比较多的。