1.<定義1>による探査

1.1m、nについての単純ループ

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乗因子を取り除いた値である。

これを前のメインループに入れて実行してもよいが、もう少しメインループの方の効率化を考える。

高速化

1. m、nは共通因子を持たないもののみ調べればよい

これは明らかであろう。

2. m、nは偶奇性が一致しないもののみを調べればよい

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) を作ると、上記により、これも解になる。
(ただし、奇数同士の組となる)。これを同値な解と呼ぶことにする。

3. m、nは2乗因子を持たないもののみ調べればよい

よって、配列 T(i)、i=1,2,…… にiから2乗因子を取り除いたものを格納しておき、
m、nの代わりに、T(m)、T(n)、T(m+n)、T(m-n) を使えばよい。

4. ここで、m、n、m+n、m−nの任意の2つは互いに素なので

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∈ は、(x/z2, y/z3), x, y, 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

この章の目次

E-mail : kc2h-msm@asahi-net.or.jp
三島 久典