|
发表于 2017-9-9 12:15:21
|
显示全部楼层
采用连分数法解Pell方程
答案:16421658242965910275055840472270471049, 661
- # encoding:utf-8
- '''
- Pell方程
- X^2 - DY^2=1
- 运用连分数理论
- '''
- from math import sqrt
- #sqrt(n) = a0+1/(a1+1/(a2+1/....+1/an))
- #the sequence is repeating, a1,a2,...ax,a1,a2,...ax
- #√13=[3;(1,1,1,1,6,1,1,1,1,6,1,1,1,1,6,...)]
- #√13=[3;(1,1,1,1,6)], period=5
- def getContinuedFractionsOfSqrt(n):
- a0 = int(sqrt(n))
- if n == a0*a0:
- return a0, []
- fractions = []
- c = 1
- b = a0
- fdict = {}
- while True:
- #(sqrt(n)-b)/c ^ -1 ==> a1 + (sqrt(n)-b1)/c1
- c1 = (n - b*b)//c
- tb = b
- #now (sqrt(n)+tb) / c1 == a1 + (sqrt(n)-b1)/c1
- # a1c1-b1==tb, b1 <= a0 ===> a1 <= (a0+tb)/c1 => a1 = (a0+tb)//c1
- a1 = (a0+tb)//c1
- b1 = a1*c1-tb
- if fdict.get((a1,b1,c1), 0) > 0:
- break
- fdict[(a1,b1,c1)] = 1
- fractions.append(a1)
- c = c1
- b = b1
- return a0, fractions
- def calculteContinuedFractions(a0, fractions, fcount):
- #return franction a/b (a,b)
- i = (fcount-1) % len(fractions)
- a,b = 1, fractions[i]
- for cnt in range(fcount-1):
- #print(a, b)
- i = (i-1) % len(fractions)
- an1 = fractions[i] #A(n-1)
- #1/(an1 + (a/b)) ===> b / (an1*b+a)
- a,b = b, an1*b+a
- #add A0, a0+(a/b) ==> (a0*b+a)/b
- a += a0*b
- return a,b
-
- def solvePell(D): #may not min X,Y
- a0, fractions = getContinuedFractionsOfSqrt(D)
- m = len(fractions)
- if m == 0:
- return 0,0
- #print(a0, fractions)
- if m%2 == 0: #even
- #x0=P(mn-1),y0=Q(mn-1), n=1,2,3...
- #n=1
- x, y = calculteContinuedFractions(a0, fractions, m-1)
- else: #odd
- #x0=P(2mn-1),y0=Q(2mn-1), n=0,1,2,3...
- #n=1
- x, y = calculteContinuedFractions(a0, fractions, 2*m-1)
- return x,y
- #print(solvePell(13)) #649, 180
- #print(solvePell(778)) #2178548422, 78104745
- maxx = 0
- saveD = 0
- for D in range(2, 1000+1):
- x,y = solvePell(D)
- if x > maxx:
- maxx = x
- saveD = D
- print(maxx, saveD) #16421658242965910275055840472270471049 661
复制代码 |
|