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∈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

前 この章の目次 次

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