プロジェクト

全般

プロフィール

Problem 66 » 履歴 » バージョン 4

Noppi, 2024/01/29 13:18

1 1 Noppi
[ホーム](https://redmine.noppi.jp) - [[Wiki|Project Euler]]
2
# [[Problem 66]]
3
4
## Diophantine Equation
5
Consider quadratic Diophantine equations of the form:
6
7
$$x^2 - Dy^2 = 1$$
8
9
For example, when $D=13$, the minimal solution in $x$ is $649^2 - 13 \times 180^2 = 1$.
10
11
It can be assumed that there are no solutions in positive integers when $D$ is square.
12
13
<p>By finding minimal solutions in $x$ for $D = \{2, 3, 5, 6, 7\}$, we obtain the following:</p>
14
\begin{align}
15
3^2 - 2 \times 2^2 &amp;= 1\\
16
2^2 - 3 \times 1^2 &amp;= 1\\
17
{\color{red}{\mathbf 9}}^2 - 5 \times 4^2 &amp;= 1\\
18
5^2 - 6 \times 2^2 &amp;= 1\\
19
8^2 - 7 \times 3^2 &amp;= 1
20
\end{align}
21
22
Hence, by considering minimal solutions in $x$ for $D \le 7$, the largest $x$ is obtained when $D=5$.
23
24
Find the value of $D \le 1000$ in minimal solutions of $x$ for which the largest value of $x$ is obtained.
25
26
## ディオファントス方程式
27
次の形式の, 2次のディオファントス方程式を考えよう:
28
29
$$x^2 - Dy^2 = 1$$
30
31
たとえば D=13 のとき, x を最小にする解は 6492 - 131802 = 1 である.
32
33
D が平方数(square)のとき, 正整数のなかに解は存在しないと考えられる.
34
35
<p>D = {2, 3, 5, 6, 7} に対して x を最小にする解は次のようになる:
36
\begin{align}
37
3^2 - 2 \times 2^2 &amp;= 1\\
38
2^2 - 3 \times 1^2 &amp;= 1\\
39
{\color{red}{\mathbf 9}}^2 - 5 \times 4^2 &amp;= 1\\
40
5^2 - 6 \times 2^2 &amp;= 1\\
41
8^2 - 7 \times 3^2 &amp;= 1
42
\end{align}
43
</p>
44
45
したがって, D ≤ 7 に対して x を最小にする解を考えると, D=5 のとき x は最大である.
46
47
D ≤ 1000 に対する x を最小にする解で, x が最大になるような D の値を見つけよ.
48
49
```scheme
50 4 Noppi
;;; こっちが正解
51
52
(import (scheme base)
53
        (gauche base)
54
        (util match)
55
        (scheme inexact))
56
57
;;; a + (√b - c) / d → (a b c d)
58
;;;
59
;;; (√b - c) / d を有理化する →
60
;;; (d * (√b + c)) / (b - c^2)
61
;;;
62
;;; d / (b - c^2) を既約分数にして 1/q と置く →
63
;;; (√b + c) / q
64
(define (next-fraction lis)
65
  (assume (= (length lis) 4))
66
  (match-let1 (a b c d)
67
              lis
68
              (let-values ([(isqrt-b _) (exact-integer-sqrt b)])
69
                (if (<= d (- (sqrt b) c))
70
                  `(,(+ a (* d isqrt-b)) ,b ,(+ c isqrt-b) ,d)
71
                  (let* ([q (/ (- b (* c c))
72
                               d)]
73
                         [next-a (div (+ isqrt-b c)
74
                                      q)]
75
                         [next-b b]
76
                         [next-c (- (* q next-a) c)]
77
                         [next-d q])
78
                    `(,next-a ,next-b ,next-c ,next-d))))))
79
80
(define (continued-fraction-list num)
81
  (assume (exact-integer? num))
82
  (assume (<= 2 num))
83
  (let* ([first-fraction (next-fraction `(0 ,num 0 1))]
84
         [first-int (car first-fraction)]
85
         [end-fraction (next-fraction first-fraction)]
86
         [result `(,(car end-fraction) ,first-int)])
87
    (let loop ([current-fraction (next-fraction end-fraction)]
88
               [result result])
89
      (if (equal? current-fraction end-fraction)
90
        (reverse result)
91
        (loop (next-fraction current-fraction)
92
              (cons (car current-fraction) result))))))
93
94
(define (cf-calc lis)
95
  (case (length lis)
96
    [(0) (errorf "cf-calcの引数が異常です : ~s~%" lis)]
97
    [(1) `(,(car lis), 1)]
98
    [else
99
      (let loop ([pn-1 (car lis)]
100
                 [pn (+ (* (car lis)
101
                           (cadr lis))
102
                        1)]
103
                 [qn-1 1]
104
                 [qn (cadr lis)]
105
                 [rest (cddr lis)])
106
        (if (null? rest)
107
          `(,pn ,qn)
108
          (loop pn
109
                (+ (* (car rest) pn)
110
                   pn-1)
111
                qn
112
                (+ (* (car rest) qn)
113
                   qn-1)
114
                (cdr rest))))]))
115
116
(define (diophantine d)
117
  (let ([cf-list (continued-fraction-list d)])
118
    (if (odd? (length cf-list))
119
      (append (cf-calc (drop-right cf-list 1))
120
              d)
121
      (let* ([temp-list-1 (cdr cf-list)]
122
             [temp-list-2 (append cf-list temp-list-1)]
123
             [temp-list (drop-right temp-list-2 1)])
124
        (append (cf-calc temp-list) d)))))
125
126
(define (non-square-num-list num)
127
  (filter (^n
128
            (let-values ([(_ b) (exact-integer-sqrt n)])
129
              (not (zero? b))))
130
          (iota (- num 1) 2)))
131
132
(define answer-66
133
  (cddr
134
    (fold (^[lis result]
135
            (if (< (car result) (car lis))
136
              lis
137
              result))
138
          `(0 0 . 0) 
139
          (map (cut diophantine <>)
140
               (non-square-num-list 1000)))))
141
142
(format #t "66: ~d~%" answer-66)
143
```
144
145
```scheme
146 2 Noppi
;;; 素直なアルゴリズムで書いたら止まらなくなったので
147
;;; このやり方は使えない
148
149
(import (scheme base)
150
        (gauche base))
151
152
(define (d-list)
153
  (filter (^n
154
            (let-values ([(_ b) (exact-integer-sqrt n)])
155
              (not (zero? b))))
156
          (iota 999 2)))
157
158
(define (diophantine d)
159
  (let loop ([y 1])
160
    (let ([dy2 (* d (square y))])
161
      (let-values ([(x-1 dif) (exact-integer-sqrt dy2)])
162
        (if (zero? dif)
163
          (loop (+ y 1))
164
          (let ([x (+ x-1 1)])
165
            (if (= (- (square x)
166
                      dy2)
167
                   1)
168 3 Noppi
              `(,x ,y . ,d)
169 2 Noppi
              (loop (+ y 1)))))))))
170
171
;;; D = 109 の時に死んだので連分数展開を使用した方法に切り替える必要がある
172
;;; ちなみに、D = 109 の時の x と y の値は次の通りらしい…
173
;;; x = 158070671986249, y = 15140424455100
174
;;; (see https://ja.wikipedia.org/wiki/%E3%83%9A%E3%83%AB%E6%96%B9%E7%A8%8B%E5%BC%8F)
175
(define (diophantine-1000)
176
  (map (cut diophantine <>)
177
       (d-list)))
178
179
(define answer-66)
180
181
(format #t "66: ~d~%" answer-66)
182 1 Noppi
```