凤凰木的笔记
登录

浅说佩尔方程(2):PQA解法

目录

本文主要讨论佩尔方程(Pell equations)

x2Dy2=1(e1)x^{2} - Dy^{2} = 1 \tag{e1}

的解法实现。

无理算术平方根的连分式展开

我们知道,任何无理算术平方根N\sqrt{N}都可以展开成循环的连分式。以 7\sqrt{7} 为例,展开如下:

7=2+72 =2+1172 =2+17+23 =2+11+713 =2+11+17+12 =2+11+11+712 =2+11+11+17+13 =2+11+11+11+1723 =2+11+11+11+14+172 =2+11+11+11+14+11+713 =2+11+11+11+14+11+11+11+14+11+713 =2+11+11+11+14+11+11+11+14+11+11+11+14+11+713 =[2;1˙,1,1,4˙]\begin{align} \sqrt{7} & = 2 + \sqrt{7} - 2\\\ & = 2 + \cfrac{1}{\cfrac{1}{\sqrt{7} - 2}}\\\ & = 2 + \cfrac{1}{\cfrac{\sqrt{7} + 2}{3}}\\\ & = 2 + \cfrac{1}{1+\cfrac{\sqrt{7} - 1}{3}}\\\ & = 2 + \cfrac{1}{1+\cfrac{1}{\cfrac{\sqrt{7}+1}{2}}}\\\ & = 2 + \cfrac{1}{1+\cfrac{1}{1+\cfrac{\sqrt{7}-1}{2}}}\\\ & = 2 + \cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{\cfrac{\sqrt{7}+1}{3}}}}\\\ & = 2 + \cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1 + \cfrac{1}{\cfrac{\sqrt{7}-2}{3}}}}}\\\ & = 2 + \cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1 + \cfrac{1}{4+\cfrac{1}{\sqrt{7}-2}}}}}\\\ & = 2 + \cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1 + \cfrac{1}{4+\cfrac{1}{1+\cfrac{\sqrt{7}-1}{3}}}}}}\\\ & = 2 + \cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1 + \cfrac{1}{4+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1 + \cfrac{1}{4+\cfrac{1}{1+\cfrac{\sqrt{7}-1}{3}}}}}}}}}}\\\ & = 2 + \cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1 + \cfrac{1}{4+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1 + \cfrac{1}{4+\cfrac{1}{1+\cfrac{1}{1+\cfrac{1}{1 + \cfrac{1}{4+\cfrac{1}{1+\cfrac{\sqrt{7}-1}{3}}}}}}}}}}}}}}\\\ & = [2;\dot{1}, 1, 1, \dot{4}] \end{align}

这种连分式展开具有很多有意思的特性,其中最有趣的可能是生成佩尔方程(Pell equations)

x2Dy2=1(15)x^{2} - Dy^{2} = 1 \tag{15}

的正整数解(其中 DD 为正整数,且非完全平方数)。

从无理算术平方根的连分式展开生成佩尔方程的解

可以证明,无理算术平方根 D\sqrt{D} 的连分式展开, 取前 nn 项约分到最简分数,某些项的分子和分母恰好是佩尔方程 (e1)(e1) 的一组正整数解,并且佩尔方程 (e1)(e1) 的所有非平凡正整数解都能从这样的展开约分中得到。

x27y2=1(16)x^{2} - 7y^{2} = 1 \tag{16}

为例,

  1. [2,1,1,1][2, 1, 1, 1] 约分,得 83\cfrac{8}{3}, 于是得到式 (16)(16) 的最小非平凡正整数解 (8,3)(8, 3) .

  2. [2,1,1,1,4,1,1,1][2, 1, 1, 1, 4, 1, 1, 1] 约分,得 12748\cfrac{127}{48}, 于是得到式 (16)(16) 的下一组非平凡正整数解 (127,48)(127, 48) .

  3. [2,1,1,1,4,1,1,1,4,1,1,1][2, 1, 1, 1, 4, 1, 1, 1, 4, 1, 1, 1] 约分,得 2024765\cfrac{2024}{765}, 于是得到式 (16)(16) 的下一组非平凡正整数解 (2024,765)(2024, 765) .

  4. 这样继续下去,我们就能得到方程 x27y2=1x^{2} - 7y^{2} = 1 的所有正整数解。

PQa 算法解佩尔方程

基于上述过程的 PQa 算法(PQa algorithm),可以求出标准佩尔方程 x2Dy2=1x^{2} - Dy^{2} = 1 的所有非平凡正整数解。

所谓 PQa 算法,根据论文 “Solving the generalized Pell equation x^2 − Dy^2 = N”(), 即:

取正整数 P0,Q0,DP_0, Q_0, D, 使得 Q00,D>0Q_0 \ne 0, D > 0, DD 不为完全平方数, 且 P02D(modQ0)P^2_0 \equiv D(mod \quad Q_0).

对任意的 i0i \geqslant 0, 令 ai=Pi+DQi,Ai=aiAi1+Ai2,Bi=aiBi1+Bi2,Gi=aiGi1+Gi2,\begin{align} & a_i = \lfloor \cfrac{P_i + \sqrt{D}}{Q_i} \rfloor, \\ & A_i = a_iA_{i-1} + A_{i-2}, \\ & B_i = a_iB_{i-1} + B_{i-2} , \\ & G_i = a_iG_{i-1} + G_{i-2} , \\ \end{align}

对任意的 i1i \geqslant 1, 令

Pi=ai1Qi1Pi1,Qi=DPi2Qi1.\begin{align} & P_i = a_{i-1}Q_{i-1} − P_{i-1}, \\ & Q_i = \cfrac{D - {P_i}^2}{Q_{i-1}} . \\ \end{align}

特别地,

A2=0,A1=1,B2=1,B1=0,G2=P0,G1=Q0.\begin{align} & A_{-2} = 0, A_{-1} = 1, \\ & B_{-2} = 1, B_{-1} = 0, \\ & G_{-2} = -P_0 , G_{-1} = Q_0 . \\ \end{align}

这样构造出来的数列 Ai,Bi,Gi,Pi,Qi,ai{A_i}, {B_i}, {G_i}, {P_i}, {Q_i}, {a_i} 具有很多有趣的性质,论文1列出了至少 27 种。其中特别需要注意的:

A. Ai,Bi,Gi,Pi,Qi,ai{A_i}, {B_i}, {G_i}, {P_i}, {Q_i}, {a_i} 全部是整数列,并且 Pi,Qi,aiP_i, Q_i, a_i 最终呈现周期性。

B.

P0+DQ0=a0+1a1+1a2+1a3+1a4+1a5+1a6+1a7+=[a0;a1,a2,a3,a4,a5,a6,a7]\begin{align} \cfrac{P_0 + \sqrt{D}}{Q_0} & = a_0+\cfrac{1}{a_1+\cfrac{1}{a_2+\cfrac{1}{a_3+\cfrac{1}{a_4+\cfrac{1}{a_5+\cfrac{1}{a_6+\cfrac{1}{a_7+\ldots}}}}}}} \\ & = [a_0;a_1,a_2,a_3,a_4,a_5,a_6,a_7\ldots] \tag{17} \end{align}

C.

P0+DQ0=limiAiBi(18)\cfrac{P_0 + \sqrt{D}}{Q_0} = \lim_{i \to \infty} \cfrac{A_i}{B_i} \tag{18}

D.

Gi12DBi12=(1)iQ0Qi,fori>0(19)G^2_{i-1} - DB^2_{i-1} = (-1)^iQ_0Q_i, for{\quad}i > 0 \tag{19}

(19){(19)} 尤为重要。只要我们取 Q0=1,i=2kQ_0 = 1, i = 2k, 式 (19){(19)} 即变为

Gi12DBi12=QiG^2_{i-1} - DB^2_{i-1} = Q_i

这表明只要 Qi=1Q_i = 1, 那么 (Gi1,Bi1)(G_{i-1}, B_{i-1}) 即为标准型佩尔方程 (e1)(e1) 的一组解。事实上,(e1)(e1) 的所有解都可以由此生成,这里略过证明。

下面用 Haskell 实现这个算法。

首先,定义一个数据结构来存储数列 Ai,Bi,Gi,Pi,Qi,ai{A_i}, {B_i}, {G_i}, {P_i}, {Q_i}, {a_i} 各项:

import Prelude hiding (pi)

data PQa = PQa { ai :: Integer
               , bi :: Integer
               , gi :: Integer
               , aj :: Integer
               , pi :: Integer
               , qi :: Integer
               } deriving Show

下面这个 pqa 函数迭代出 [(PQai,PQai1)][({PQa}_{i}, {PQa}_{i-1})] 的无穷数列:

pqas :: Integer -> Integer -> Integer -> [(PQa, PQa)]
pqas d p0 q0 = iterate pqa' (pqa0, pqa_1) where
    pqa0 = PQa { ai = c
               , bi = 1
               , gi = c * q0 - p0
               , aj = c
               , pi = p0
               , qi = q0
               }
    pqa_1 = PQa { ai = 1
                , bi = 0
                , gi = q0
                , aj = c
                , pi = 1
                , qi = 1
                }
    c = floor $ (fromInteger p0 + sqrt (fromInteger d)) / (fromInteger q0)
    pqa' :: (PQa, PQa) -> (PQa, PQa)
    pqa' (acc, acc') = (acc'', acc) where
        pi' = (aj acc) * (qi acc) - pi acc
        qi' = quot (d - pi'^2) (qi acc)
        aj' = floor $ (fromInteger pi' + sqrt (fromInteger d)) / (fromInteger qi')
        ai' = aj' * (ai acc) + ai acc'
        bi' = aj' * (bi acc) + bi acc'
        gi' = aj' * (gi acc) + gi acc'
        acc'' = PQa { ai = ai'
                    , bi = bi'
                    , gi = gi'
                    , aj = aj'
                    , pi = pi'
                    , qi = qi'
                    }

P0=0,Q0=1P_0 = 0, Q_0 = 1, 得到

pqas01 :: Integer -> [(PQa, PQa)]
pqas01 d = pqas d 0 1

滤掉 Qi1Q_i \ne 1 的项,就得到标准佩尔方程 (e1)(e1) 的所有非平凡正整数解,这个结果以 Haskell 的惰性无穷列表来表示:

pqaSolutions01 :: Integer -> [(Integer, Integer)]
pqaSolutions01 d = map (\(x, y) -> (gi y, bi y)) $ filter (\(x, y) -> qi x == 1 && bi y /= 0) $ pqas01 d

然后求最小正整数解只要取第一项就可以了:

minimumPositiveSolution :: Integer -> (Integer, Integer)                   
minimumPositiveSolution = head . pqaSolutions01

比如我们来求佩尔方程 x27y2=1x^{2} - 7y^{2} = 1 的最小前 3030 组非平凡解,只需要在 ghci 里:

> mapM_ print $ take 40 $ pqaSolutions01 7
(8,3)
(127,48)
(2024,765)
(32257,12192)
(514088,194307)
(8193151,3096720)
(130576328,49353213)
(2081028097,786554688)
(33165873224,12535521795)
(528572943487,199781794032)
(8424001222568,3183973182717)
(134255446617601,50743789129440)
(2139663144659048,808716652888323)
(34100354867927167,12888722657083728)
(543466014742175624,205410845860451325)
(8661355881006882817,3273684811110137472)
(138038228081367949448,52173546131901748227)
(2199950293420880308351,831503053299317834160)
(35061166466652716984168,13251875306657183598333)
(558778713173022591438337,211198501853215619739168)
(8905398244301708746029224,3365924154344792732228355)
(141927593195654317345029247,53643587967663468095914512)
(2261936092886167368774438728,854931483328270696802403837)
(36049049892983023583045990401,13625260145284667680742546880)
(574522862194842209959961407688,217149230841226412195078346243)
(9156316745224492335776336532607,3460762433314337927440510993008)
(145926545061397035162461423114024,55155049702188180426853097541885)
(2325668404237128070263606433291777,879020032801696548902209049677152)
(37064767922732652089055241509554408,14009165475124956602008491697292547)
(590710618359485305354620257719578751,223267627569197609083233658107003600)
(9414305125829032233584868882003705608,3558272875632036788729730038014765053)
(150038171394905030432003281854339710977,56709098382543391010592446950129237248)
(2391196437192651454678467640787431670024,903787301245062219380749421164053030915)
(38109104823687518244423478970744567009407,14403887721538452119081398291674719257392)
(607354480741807640456097195891125640480488,229558416243370171685921623245631455087357)
(9679562587045234729053131655287265680678401,3658530772172384294855664573638428562140320)
(154265646911981948024394009288705125250373928,58306933938514778546004711554969225539157763)
(2458570788004665933661251016963994738325304447,929252412244064072441219720305869180064383888)
(39182866961162672990555622262135210687954497224,14809731661966510380513510813338937655490984445)
(624467300590598101915228705177199376268946651137,236026454179220102015774953293117133307791367232)

可以看到,解的数值以一种相当恐怖的速度增长(事实上是以指数增长的)。

简单看下对不同的 DD, 佩尔方程 e1e1 最小非平凡正整数解的分布情况。

minimumPositiveSolutions :: Integer -> [(Integer, (Integer, Integer))]
minimumPositiveSolutions n = map (\x -> (x, minimumPositiveSolution x)) xs where
    xs = filter (\x -> let y = (round $ sqrt $ fromInteger x) in y^2 /= x) [1..n]

n=100n = 100, 得到 2D992 \leqslant D \leqslant 99 范围内的最小非平凡正整数解,如下表:

DDxxyy
223322
332211
559944
665522
778833
883311
1010191966
1111101033
12127722
1313649649180180
1414151544
15154411
1717333388
1818171744
19191701703939
20209922
212155551212
22221971974242
2323242455
24245511
262651511010
2727262655
28281271272424
29299801980118201820
3030111122
313115201520273273
3232171733
3333232344
3434353566
35356611
373773731212
3838373766
3939252544
4040191933
414120492049320320
4242131322
434334823482531531
44441991993030
45451611612424
4646243352433535883588
4747484877
48487711
505099991414
5151505077
52526496499090
5353662496624991009100
54544854856666
555589891212
5656151522
57571511512020
5858196031960325742574
59595305306969
6060313144
616117663190491766319049226153980226153980
6262636388
63638811
65651291291616
6666656588
6767488424884259675967
6868333344
696977757775936936
70702512513030
717134803480413413
7272171722
737322812492281249267000267000
747436993699430430
7575262633
7676577995779966306630
77773513514040
7878535366
7979808099
80809911
82821631631818
8383828299
8484555566
85852857692857693099630996
8686104051040511221122
8787282833
88881971972121
89895000015000015300053000
9090191922
919115741574165165
929211511151120120
9393121511215112601260
949421432952143295221064221064
9595393944
9696494955
9797628096336280963363773526377352
989899991010
9999101011

可见,最大的一组是 D=61D = 61 时,(x,y)=(1766319049,226153980)(x, y) = (1766319049, 226153980).

> take 10 $ sortBy (\(_, (x1, _)) (_, (x2, _)) -> compare x2 x1 ) $ minimumPositiveSolutions 1000

得到 D1000D \leqslant 1000 时,最大的前 10 组:

DDxxyy
66116421658242965910275055840472270471049638728478116949861246791167518480580
5413707453360023867028800645599667005001159395869721270110077187138775196900
4213879474045914926879468217167061449189073995951839020880499780706260
76953578186838888131085970230842320119320788325040337217824455505160
93748064442500241599959711310723315701968936415353889062192632
61346401887358407827891099429984918741545784831997880308784340
99137951640090681193063801489608012055735790331359447442538767
601389028154624923184203114780491586878942101888360258625080
6734765506835465395993032041249183696788896587421699032600
9194481603010937119451551263720147834442396536759781499589
> maximumBy (\(_, (x1, _)) (_, (x2, _)) -> compare x1 x2 ) $ minimumPositiveSolutions 10000

得到 D104D \leqslant 10^4 时,最大的一组是当 D=9949D = 9949 时,

(x, y) = (23551019614858223475933893515741198183163217312913587552899320396564478041197360918469501097146448985821854465768234479384482435117587576296319428592757548743265811454938493105633433315887574461850060798834186249,236113054062810988826514929828649213339688520849720684015415366388626019230322623673232286474879711003505448178417385617250641629212134427833135509077013929303770208680820795381507114806491325360400076633910900)

同样的办法,可以得到 D105D \leqslant 10^5,最大的一组是当 D=92821D=92821 时,

(x, y) = (9138623307350640837938507246130056541284450249628186652711211526290141593088447074959889691586109808446586788487329855457947449359122812196406183471094085243300140113776722320673519989258197664615506581635543258793642137960637895993371068043922291726707457424732865511811603416709407607285667077345150397643032877987726841522351750655900253781916899660152174806370963781778224969807395941841736594668461346490187409918540644500596164105739747237839541686461147582701486262272823400803243678345216257264359841059899047944315969645240323636858831783554703663860186919961543958325467259751629633944639211198469786177829884186709831569216425531620090438319686256712276877552760998820897069126292769743115626179169131031894821449, 29995606985908278391394125599135320972040960690735594014932999302562021607917845625308781046774668965028391500344676078764117785968987025596642346687378667667268554217805689486419938846247966636235622466824853671443727025761340681500617596724921086840802447598463611192953164168684707145263201173090354218890224078617132621981270144387271894050379162839910605924620561997843353743092508084766465038567232036892276652930541497664634108271302723027950641070447197899109815123567584348859003464872979489356061130456764804964145771699318883015346111831572404557647659469760522059443590269944115798752448599110602793086535348170280145151753392282563680433826089979371590683960862942643266548255841329663100421901070962552821740)

D108D \leqslant 10^8 时,

indexDDxx 位数yy 位数
11974706197470618982898289798979
22967062196706218682868286788678
33955486995548698625862586218621
44972678197267818527852785248524
55969754996975498515851585128512
66996534199653418493849384898489
77954990195499018493849384908490
88992362999236298480848084778477
99950866995086698437843784338433
1010865858986585898404840484018401
1111923370192337018402840283998399
1212989514198951418343834383408340
1313995706199570618341834183378337
1414988218198821818303830383008300
1515990598999059898267826782648264
1616868714986871498235823582328232
1717905866990586698229822982268226
1818898354989835498222822282198219
1919943126994312698209820982058205
2020949966994996698159815981558155
2121886662188666218155815581528152
2222983482998348298150815081478147
2323985314198531418129812981258125
2424867522186752218123812381198119
2525869158986915898122812281188118
2626934458193445818121812181178117
2727988086198808618114811481108110
2828994114999411498109810981058105
2929957306195730618105810581018101
3030977398997739898102810280988098
3131936922993692298085808580828082
3232861514986151498076807680728072
3333934258993425898061806180578057
3434985080198508018043804380398039
3535925732992573298018801880148014
3636926926992692698014801480108010
3737967654996765498008800880058005
3838911710991171098005800580028002
3939984366198436618005800580018001
4040983782998378297999799979967996
4141979510997951097993799379897989
4242882582188258217986798679837983
4343994518199451817976797679727972
4444931378993137897953795379507950
4545835626183562617952795279497949
4646909714190971417942794279397939
4747976176197617617940794079367936
4848991984999198497940794079377937
4949806142180614217935793579317931
5050897702189770217931793179287928
5151793474979347497928792879257925
5252923890992389097911791179087908
5353982438998243897892789278887888
5454992992999299297886788678837883
5555955006995500697885788578827882
5656995904199590417884788478807880
5757966042196604217879787978767876
5858853366985336697877787778737873
5959980868198086817868786878657865
6060954756195475617864786478617861
6161957612195761217862786278597859
6262848458984845897858785878557855
6363979114997911497845784578417841
6464934050193405017842784278387838
6565871810987181097839783978367836
6666933586993358697836783678337833
6767921382992138297830783078267826
6868969034996903497820782078177817
6969969780196978017817781778137813
7070997326199732617812781278087808
7171962038996203897803780378007800
7272899886189988617802780277987798
7373962626996262697799779977957795
7474979996997999697798779877947794
7575928342992834297796779677937793
7676950880195088017794779477917791
7777997962199796217782778277797779
7878998796199879617779777977757775
7979831642183164217777777777747774
8080958914195891417774777477717771
8181903226990322697772777277687768
8282962760196276017771777177687768
8383856270985627097763776377607760
8484980862198086217762776277587758
8585990118999011897761776177587758
8686988260198826017754775477507750
8787849966184996617752775277497749
8888904506190450617741774177377737
8989748594974859497739773977367736
9090923818992381897733773377307730
9191985714998571497730773077267726
9292941440994144097726772677237723
9393999166999916697724772477207720
9494945756194575617720772077177717
9595895440189544017720772077177717
9696772626177262617714771477107710
9797971958197195817708770877057705
9898978124997812497707770777047704
9999857514185751417705770577027702
100100895030989503097700770076967696

我顺便把上面这个 Haskell 实现写成了 Web API。这个 API 接受 d, 和 n 两个参数。其中 d 即方程里的参数 DD, 而 n 表示数出方程的前 n 组最小整整数解。url 是 /v1/pell.

受服务器物理限制,有范围: 0<d<1090 \lt d \lt 10^9, 0<n<1000 \lt n \lt 100.

举例:

  • x27y2=1x^{2} - 7y^{2} = 1 的最小前 3030 组非平凡解: https://www.weiwen.org/v1/pell?d=7&n=30

  • x2991y2=1x^{2} - 991y^{2} = 1 的最小前 1010 组非平凡解(小心,非常大): https://www.weiwen.org/v1/pell?d=991&n=10

我还写了个更直观的页面,可以点进去玩一下: https://www.weiwen.org/pell

(本文完)

Solving the generalized Pell equation x^2 − Dy^2 = N, John P. Robertson, 2004