鱼C论坛

 找回密码
 立即注册
查看: 6754|回复: 6

题目66:考察丢番图方程x^2 − Dy^2 = 1

[复制链接]
发表于 2015-10-14 15:15:30 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Diophantine equation

Consider quadratic Diophantine equations of the form:

QQ20151014-2@2x.png

For example, when D=13, the minimal solution in x is QQ20151014-1@2x.png

It can be assumed that there are no solutions in positive integers when D is square.

By finding minimal solutions in x for D = {2, 3, 5, 6, 7}, we obtain the following:

QQ20151014-3@2x.png

Hence, by considering minimal solutions in x for D ≤ 7, the largest x is obtained when D=5.

Find the value of D ≤ 1000 in minimal solutions of x for which the largest value of x is obtained.

题目:

考虑如下形式的二次丢番图方程:

QQ20151014-2@2x.png

例如当 D=13 时, x 的最小解是 QQ20151014-1@2x.png

可以认为当 D 时平方数时方程无正整数解。

通过寻找当 D = {2, 3, 5, 6, 7} 时 x 的最小解,我们得到:

QQ20151014-3@2x.png

因此对于 D ≤ 7, x 的最小解的最大值在 D=5 时取到。

找出 D ≤ 1000 中使得 x 的最小值取到最大的 D 的值。

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2016-12-24 23:42:55 | 显示全部楼层
最笨最暴力的解法:
  1. #coding:utf-8
  2. maxx = 1
  3. for D in range(2,1001):
  4.         print (D)
  5.         if (D**0.5) % 1 != 0:
  6.                 y = 1
  7.                 while True:
  8.                         x = (D * y * y + 1) ** 0.5
  9.                         if x % 1 == 0:
  10.                                 if x > maxx:
  11.                                         maxx = int(x)
  12.                                 break
  13.                         else:
  14.                                 y += 1
  15. print (maxx)
复制代码

2178548422
[Finished in 2751.0s]
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-12-25 00:00:52 | 显示全部楼层
2178548422 * 2178548422 - 778 * 78104745 * 78104745 = 1
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-1-24 10:09:25 | 显示全部楼层
  1. # encoding:utf-8
  2. # x**2 - D*y**2 = 1
  3. from time import time
  4. from math import sqrt
  5. def euler066():
  6.     max_x, r_D, r_y = 0, 0, 0
  7.     for D in range(2, 1001):
  8.         if int(sqrt(D)) == sqrt(D):
  9.             continue
  10.         y = 0
  11.         flag = False
  12.         while not flag:
  13.             y += 1
  14.             x = sqrt(D * (y ** 2) + 1)
  15.             if x == int(x):
  16.                 print(D, int(x), y)
  17.                 y = 1
  18.                 if int(x) > max_x:
  19.                     max_x, r_D, r_y = int(x), D, y
  20.                 flag = True
  21.                 break
  22.     print(max_x, r_D, r_y)
  23. if __name__ == '__main__':
  24.     start = time()
  25.     euler066()
  26.     print('cost %.6f sec' % (time() - start))
复制代码


跑到D=500多等不了了....
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-9 12:15:21 | 显示全部楼层
采用连分数法解Pell方程
答案:16421658242965910275055840472270471049, 661
  1. # encoding:utf-8
  2. '''
  3. Pell方程
  4. X^2 - DY^2=1
  5. 运用连分数理论
  6. '''
  7. from math import sqrt

  8. #sqrt(n) = a0+1/(a1+1/(a2+1/....+1/an))
  9. #the sequence is repeating, a1,a2,...ax,a1,a2,...ax
  10. #√13=[3;(1,1,1,1,6,1,1,1,1,6,1,1,1,1,6,...)]
  11. #√13=[3;(1,1,1,1,6)], period=5
  12. def getContinuedFractionsOfSqrt(n):
  13.         a0 = int(sqrt(n))
  14.         if n == a0*a0:
  15.                 return a0, []

  16.         fractions = []
  17.         c = 1
  18.         b = a0
  19.         fdict = {}
  20.         while True:
  21.                 #(sqrt(n)-b)/c ^ -1 ==> a1 + (sqrt(n)-b1)/c1
  22.                 c1 = (n - b*b)//c
  23.                 tb = b
  24.                 #now (sqrt(n)+tb) / c1 == a1 + (sqrt(n)-b1)/c1
  25.                 # a1c1-b1==tb, b1 <= a0 ===> a1 <= (a0+tb)/c1 => a1 = (a0+tb)//c1
  26.                 a1 = (a0+tb)//c1
  27.                 b1 = a1*c1-tb
  28.                 if fdict.get((a1,b1,c1), 0) > 0:
  29.                         break
  30.                 fdict[(a1,b1,c1)] = 1
  31.                 fractions.append(a1)
  32.                 c = c1
  33.                 b = b1

  34.         return a0, fractions

  35. def calculteContinuedFractions(a0, fractions, fcount):
  36.         #return franction a/b (a,b)
  37.         i = (fcount-1) % len(fractions)
  38.         a,b = 1, fractions[i]
  39.         for cnt in range(fcount-1):
  40.                 #print(a, b)
  41.                 i = (i-1) % len(fractions)
  42.                 an1 = fractions[i] #A(n-1)
  43.                 #1/(an1 + (a/b)) ===> b / (an1*b+a)
  44.                 a,b = b, an1*b+a
  45.         #add A0, a0+(a/b) ==> (a0*b+a)/b
  46.         a += a0*b
  47.         return a,b       

  48.        
  49. def solvePell(D): #may not min X,Y
  50.         a0, fractions = getContinuedFractionsOfSqrt(D)
  51.         m = len(fractions)
  52.         if m == 0:
  53.                 return 0,0
  54.         #print(a0, fractions)

  55.         if m%2 == 0: #even
  56.         #x0=P(mn-1),y0=Q(mn-1), n=1,2,3...
  57.         #n=1
  58.                 x, y = calculteContinuedFractions(a0, fractions, m-1)
  59.         else: #odd
  60.         #x0=P(2mn-1),y0=Q(2mn-1), n=0,1,2,3...
  61.         #n=1
  62.                 x, y = calculteContinuedFractions(a0, fractions, 2*m-1)       
  63.         return x,y

  64. #print(solvePell(13)) #649, 180
  65. #print(solvePell(778)) #2178548422, 78104745

  66. maxx = 0
  67. saveD = 0
  68. for D in range(2, 1000+1):
  69.         x,y = solvePell(D)
  70.         if x > maxx:
  71.                 maxx = x
  72.                 saveD = D
  73. print(maxx, saveD) #16421658242965910275055840472270471049 661
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2018-7-30 10:56:47 | 显示全部楼层
def findx(n):   
    m = int(n**0.5)
    if  m * m == n :
        return 0
    ha,ka = 1, 0
    d,a,b,c = m, n, -m,1
    hb = d; kb = 1
    if hb * hb - n * kb * kb == 1:
       return hb
    while True:
        nC = a - b * b
        nC = nC / c
        nd = int((a**0.5 - b) / nC)
        nb = -b - nd * nC
        c = nC; d = nd; b = nb
        hc = d*hb+ha
        kc = d * kb + ka
        ha,ka,hb,kb = hb,kb,hc,kc        
        if hc*hc==kc*kc*n+1:
            return hc         
    return 0


ans = 0; tmp = 0
for i in range(1,1001):
    z = findx(i)
    if z > tmp:
        tmp=z
        ans=i

print(ans, tmp)

661 16421658242965910275055840472270471049
[Finished in 0.1s]
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-4-26 10:41:56 | 显示全部楼层
本帖最后由 guosl 于 2021-3-21 11:58 编辑

方程x^2-Dy^2=1的解可以通过将D的平方根展开成连分数来得到。时间可以控制到0.01秒以下。
  1. #include <iostream>
  2. #include <vector>
  3. #include <cmath>
  4. #include <algorithm>
  5. #include <mpirxx.h>
  6. using namespace std;

  7. int gcd(int x, int y)
  8. {
  9.   if (y == 0)
  10.     return x;
  11.   int z = x % y;
  12.   while (z != 0)
  13.   {
  14.     x = y;
  15.     y = z;
  16.     z = x % y;
  17.   }
  18.   return y;
  19. }

  20. int gcd3(int x, int y, int z)
  21. {
  22.   int a = gcd(x, y);
  23.   a = gcd(a, z);
  24.   return a;
  25. }

  26. struct stTriples
  27. {
  28.   int a, b, c;
  29.   bool operator==(const stTriples &t) const
  30.   {
  31.     return (a == t.a && b == t.b && c == t.c);
  32.   }
  33. };

  34. void get_triples(int nD, const stTriples &tr1, int &n, stTriples &tr2)
  35. {
  36.   int a1 = tr1.a * tr1.c, b1 = -tr1.b * tr1.c, c1 = tr1.a * tr1.a * nD - tr1.b * tr1.b;
  37.   n = int((sqrt(nD) * double(a1) + double(b1)) / double(c1));
  38.   b1 -= n * c1;
  39.   int k = gcd3(abs(a1), abs(b1), abs(c1));
  40.   a1 /= k;
  41.   b1 /= k;
  42.   c1 /= k;
  43.   tr2.a = a1;
  44.   tr2.b = b1;
  45.   tr2.c = c1;
  46. }

  47. int get_cycle(int nD, vector<int>& vI)
  48. {
  49.   int p = 0;
  50.   int q = int(sqrt((double)nD));
  51.   vI.push_back(q);
  52.   if (q * q == nD)
  53.     return 0;
  54.   vector<stTriples> vTriples;
  55.   stTriples tr1, tr2;
  56.   tr1.a = 1;
  57.   tr1.b = -q;
  58.   tr1.c = 1;
  59.   int n;
  60.   while (true)
  61.   {
  62.     get_triples(nD, tr1, n, tr2);
  63.     auto itr = find(vTriples.begin(), vTriples.end(), tr2);
  64.     if (itr != vTriples.end())
  65.     {
  66.       p = int(vTriples.end() - itr);
  67.       break;
  68.     }
  69.     vI.push_back(n);
  70.     vTriples.push_back(tr2);
  71.     tr1 = tr2;
  72.   }
  73.   return p;
  74. }

  75. int main(void)
  76. {
  77.   mpz_class xMax = 0;
  78.   int nD = 0;
  79.   for (int k = 2; k < 1000; ++k)
  80.   {
  81.     vector<int> vI;
  82.     int n = get_cycle(k, vI);
  83.     if (n == 0)
  84.       continue;
  85.     int m = vI.size();
  86.     int s = m - n;
  87.     int kk = n - 1;
  88.     if ((n & 1) == 1)
  89.     {
  90.       kk = 2 * n - 1;
  91.       for (int i = s; i < m; ++i)
  92.         vI.push_back(vI[i]);
  93.     }
  94.     mpz_class p[3], q[3];
  95.     p[0] = vI[0], p[1] = vI[0] * vI[1] + 1;
  96.     q[0] = 1, q[1] = vI[1];
  97.     for (int i = 2; i <= kk; ++i)
  98.     {
  99.       p[2] = vI[i] * p[1] + p[0];
  100.       q[2] = vI[i] * q[1] + q[0];
  101.       p[0] = p[1];
  102.       p[1] = p[2];
  103.       q[0] = q[1];
  104.       q[1] = q[2];
  105.     }
  106.     if (p[1] > xMax)
  107.     {
  108.       xMax = p[1];
  109.       nD = k;
  110.     }
  111.   }
  112.   cout << nD << endl;
  113.   return 0;
  114. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-11 16:00

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表