午後のひとときに数学の問題を解いてみる。
数学問題
以下の問題の自然数x、yをすべて求めよ。
但し、x<yとする。
(1) x2+y2=61
(2) x2+y2=612
(3) x2+y2=613
(4) x2+y2=614
(5) x2+y2=615
プログラミング問題
数学問題を踏まえて、
x2+y2=61n
0<n<11
を効率よくx, yをみつけるプログラムを作れ。
シンキングタ~イム
(1)
まず、右辺に着目すると、下一桁が1である。
2乗したものを足したら下一桁が1になるには、
つまり、mod 10を考えると、
02≡0 (mod 10)
12≡1 (mod 10)
22≡4 (mod 10)
32≡9 (mod 10)
42≡6 (mod 10)
52≡5 (mod 10)
62≡6 (mod 10)
72≡9 (mod 10)
82≡4 (mod 10)
92≡1 (mod 10)
ですので、これらから2つを足して1になるには、
0と1、0と9、4と5、5と6の組み合わせしか無い。
また、61は平方数でなく、102=100なので、0を使った組み合わせは存在しない。
42+52=41
52+62=61
というわけで、
答え x=5、y=6
(2)
(1)を踏まえて、ピタゴラス数の一般式、
m>n, m, n∈N
x=m2-n2
y=2mn
z=m2+n2
を使い、
z=61とすると、m=6、n=5なので、
x=11、y=60、z=61となる。
答え x=11、y=60
(3)
(1)と(2)を踏まえると、
(52+62)(112+602)=613
ですので、
(52+62)612=613
3052+3662=613
となる。
但し、これだけが唯一の解かどうかが解らない。
そこで、mod 100を考えると、
613≡81 (mod 100)
になるには、
25+56≡81 (mod 100)
の組み合わせしかない。
25は10通り、56は4通りなので、56を基準に考えてみる。
613/2<477なので、
16、34、66、92、
116、134、166、192、
216、234、266、292、
316、334、366、392
416、434、466
を調べる。
答え (x,y)={ (234, 415), (305, 366) }
(4)
これまでを踏まえると、
(112+602)(112+602)=614
6712+36602=614
が容易にみつかるが、これだけとは限らない。
(3)で解が2個見つかっていることから、最低でも2個はみつかると考える。
(4)以降は面倒なので、もう少し数学的な考証をしたのち、プログラムを書いてみる。
61nのmod 100を考えてみる。
611≡61 (mod 100)
612≡21 (mod 100)
613≡81 (mod 100)
614≡41 (mod 100)
615≡1 (mod 100)
の5パターンしか存在しません。
そこで、2乗した値のmod 10は、
02≡0 (mod 10)と、112, 212, 312, 412, 512, 612, 712, 812, 912 (mod 100)
52≡25 (mod 10)と、62, 162, 262, 362, 462, 562, 662, 762, 862, 962 (mod 100)
の組み合わせしか存在しない。
左側を採用しても、右側を採用しても、増加量は5なので、どちらを採用したとしても、差異はないだろう。
よって、プログラミングするならば、片方を5の倍数で探すのが、おそらく簡単で効率が良いと考えられる。
#include <stdlib.h>
#include <math.h>
int main()
{
unsigned long long x, y, z, f;
int n;
z=61;
f=sqrtl(z)+0.5L;
n=1;
while ( z <= 713342911662882601 ) {
for (x=5; x<=f; x+=5) {
y = sqrtl(z-x*x)+0.5L;
if ( x*x+y*y == z ) printf("%d\t%llu\t%llu\n", n, x, y);
}
z *= 61;
f=sqrtl(z)+0.5L;
n++;
}
return EXIT_SUCCESS;
}
出力結果は、
n | x | y |
1 | 5 | 6 |
2 | 60 | 11 |
3 | 305 | 366 |
3 | 415 | 234 |
4 | 1320 | 3479 |
4 | 3660 | 671 |
5 | 9475 | 27474 |
5 | 18605 | 22326 |
5 | 25315 | 14274 |
6 | 80520 | 212219 |
6 | 194220 | 117469 |
6 | 223260 | 40931 |
7 | 577975 | 1675914 |
7 | 1134905 | 1361886 |
7 | 1544215 | 870714 |
7 | 1752665 | 266286 |
8 | 4911720 | 12945359 |
8 | 9184560 | 10361041 |
8 | 11847420 | 7165609 |
8 | 13618860 | 2496791 |
9 | 3302155 | 108089046 |
9 | 35256475 | 102230754 |
9 | 69229205 | 83075046 |
9 | 94197115 | 53113554 |
9 | 106912565 | 16243446 |
10 | 299614920 | 789666899 |
10 | 520632300 | 665045051 |
10 | 560258160 | 632023501 |
10 | 722692620 | 437102149 |
10 | 830750460 | 152304251 |
実は、もう少しだけ効率のよいプログラムが書けます。
どこをどうすれば良いでしょうか。
ではでは