3辺a、b、cが有理数となる直角3角形の面積gとして表される数を合同数(congruum)と呼ぶ。
a、b、cが自然数の場合、a、bが直角を挟む辺とすると、直角3角形の面積sは、
s=ab/2
kを、s=k2g、(kは1以上の自然数、gは2乗因子を含まない)と定義し、両辺をk2で割ると、
g=(a/k)(b/k)/2
よって、合同数の定義は、
「3辺a、b、cが自然数となる直角3角形の面積sから2乗因子を取り除いた数として表される自然数g」
と云いかえることができる。
3辺が互いに素な自然数となる直角3角形の3辺a、b、cは以下の式で表される。
a=m2−n2
b=2mn
c=m2+n2
(m、nは任意の自然数)
この直角3角形の面積 s は、s=mn(m2−n2)となる。
sの2乗因子をkをすると、s=k 2g=mn(m2−n2) 。
例えば、
m=2、n=1
に対し、
a=m2−n2=22−12=3
b=2mn=2・2・1=4
となり、
s=mn(m2−n2)=2・1(22−12)=6
であるから、6は合同数である。
ここで、関数 T(n) を「任意の自然数nに対し、nの2乗因子を取り除いたもの」とすると、
合同数の定義式は、
g=T(m)T(n)T(m+n)T(m-n)
となる。
ある値以下のm、nについてg<1000となるケースを探してみる。メインループは、
for m=1 to 10^6 for n=1 to m-1 g=t(m)*t(n)*t(m+n)*t(m-n) if g<1000 then print g,m,n next n next m
となる。
2乗因子を取り除くためのアルゴリズムは以下のとおり。
10 fnSub(N) 20 local P,W=1 30 P=prmdiv(N):if P=0 then return(N) 40 N=N\P:if N@P=0 then N=N\P else W=W*P 50 if N=1 then return(W) else goto 30
まず、最小素因数で1回割る。
2回目も割れるときは2乗因子、割れない場合は2乗因子ではないのでwに値をセットする。
nが1になったときのwの値が、nから2乗因子を取り除いた値である。
これを前のメインループに入れて実行してもよいが、もう少しメインループの方の効率化を考える。
これは明らかであろう。
m、nともに偶数のときは、上のとおり。
m、nともに奇数のとき、
m+n
m−n
は共に偶数であり、共通因子2を持つ。
よって、M=(m+n)/2、N=(m−n)/2 とおくと、M<m、N<n。
従って、m、nを調べる前に、既にM、Nが調べられている。
上記2つの条件を満たすm、nについて、
m、n、m+n、m−n
の内、任意の2つは、互いに素となる(これも容易に確かめられる)。
この時、m、n、m+n、m−nは、
m、nのどちらかは偶数
残りの3個は奇数
となる。このときの解を原始的な解と呼ぶ。
また、原始的な解 (m, n) から (m+n, m-n) を作ると、上記により、これも解になる。
(ただし、奇数同士の組となる)。これを同値な解と呼ぶことにする。
よって、配列 T(i)、i=1,2,…… にiから2乗因子を取り除いたものを格納しておき、
m、nの代わりに、T(m)、T(n)、T(m+n)、T(m-n) を使えばよい。
g=T(m)T(n)T(m+n)T(m-n)
は2乗因子を持たない。
また、gの4つの因子 T(m)、T(n)、T(m+n)、T(m-n) について、1つでも1000を越えると、g>1000となる。
よって、1000を越えた時点で次のm、nに移ってよい。
以上、1.〜4.で処理速度は格段に向上する。原始的な解を求めるためのプログラムは以下のとおり。
10 ' cong_1.ub 20 K%=1000 30 L%=10000:dim T%(2*L%+1) 40 for I%=1 to 2*L%+1:T%(I%)=fnSub(I%):next I% 50 ' 60 for M%=2 to L%:if T%(M%)>=K% then 160 70 for N%=1 to M%-1:if T%(N%)>=K% then 150 80 if even(M%+N%) then 150 90 if gcd(M%,N%)>1 then 150 100 if T%(M%+N%)>=K% then 150 110 if T%(M%-N%)>=K% then 150 120 G=T%(M%)*T%(N%)*T%(M%+N%)*T%(M%-N%) 130 if G>=K% then 150 140 print G,M%,N% 150 next N% 160 next M% 170 end 180 ' 190 fnSub(N) 200 local P,W=1 210 P=prmdiv(N):if P=0 then return(N) 220 N=N\P:if N@P=0 then N=N\P else W=W*P 230 if N=1 then return(W) else goto 210
M%、N% を integer を超す範囲までループで廻したい場合は、まず、M%、N% を 多倍長型に変更する。
それから、UBASIC では配列として割り当てられる個数に制限があるので、
ある値以上については、T%( ) に格納するのではなく、直接 fnSub(N) を呼び出す形とする。
また、この m、n 及び、k2g=mn(m2−n2) となる k に対して、
X=mg/n
Y=kg2/n2
とおくと、点 (X, Y) は、楕円曲線 Y2=X3-g2X 上の有理点となる。
かつ、楕円曲線上の有理点 (X, Y), X, Y∈Q は、(x/z2, y/z3),
x, y, z∈Z と表すことができる。
解となる M%、N% が見つかった時、この x, y, z も合わせて計算することにする。
『数論における未解決問題集』によると、1000以下の合同数は全部で361個ある。
100万以下のm、nについて調べたところ、そのうち、198個について解が求められた。
実行結果は以下のとおり。
解が見つからなかったのは、以下の163個。
47, 53, 61, 79, 101, 103, 118, 127, 134, 142, 157, 166, 167, 173, 181, 183, 191, 197, 199, 206, 213, 223, 229, 237, 247, 262, 263, 269, 271, 277, 278, 287, 293, 302, 303, 309, 311, 317, 326, 327, 334, 335, 349, 358, 359, 365, 367, 373, 382, 383, 389, 397, 398, 407, 413, 415, 421, 431, 437, 439, 446, 447, 453, 454, 461, 463, 469, 471, 478, 479, 485, 487, 493, 501, 502, 503, 511, 519, 526, 533, 541, 542, 543, 557, 559, 566, 573, 583, 589, 591, 597, 599, 607, 613, 614, 623, 631, 638, 647, 653, 655, 661, 662, 677, 678, 679, 685, 687, 695, 701, 703, 717, 718, 719, 727, 733, 742, 743, 757, 758, 766, 767, 773, 781, 789, 797, 807, 815, 821, 822, 823, 829, 831, 838, 839, 853, 862, 863, 871, 877, 878, 886, 887, 893, 894, 902, 911, 917, 919, 926, 933, 941, 942, 958, 965, 967, 974, 982, 983, 989, 991, 997, 998
前 | この章の目次 | 次 |
---|