Quantcast
Channel: 円周率近似値の日に生まれて理系じゃないわけないだろ! - knifeのblog
Viewing all articles
Browse latest Browse all 5376

x²+y²=61ⁿを満たすx,yを求めよ

$
0
0

午後のひとときに数学の問題を解いてみる。

数学問題
以下の問題の自然数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, 91(mod 100)
52≡25 (mod 10)と、62, 162, 262, 362, 462, 562, 662, 762, 862, 962 (mod 100)
の組み合わせしか存在しない。

左側を採用しても、右側を採用しても、増加量は5なので、どちらを採用したとしても、差異はないだろう。

よって、プログラミングするならば、片方を5の倍数で探すのが、おそらく簡単で効率が良いと考えられる。
 

#include <stdio.h>
#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;
}

 

出力結果は、

 

nxy
156
26011
3305366
3415234
413203479
43660671
5947527474
51860522326
52531514274
680520212219
6194220117469
622326040931
75779751675914
711349051361886
71544215870714
71752665266286
8491172012945359
8918456010361041
8118474207165609
8136188602496791
93302155108089046
935256475102230754
96922920583075046
99419711553113554
910691256516243446
10299614920789666899
10520632300665045051
10560258160632023501
10722692620437102149
10830750460152304251


実は、もう少しだけ効率のよいプログラムが書けます。
どこをどうすれば良いでしょうか。


ではでは


Viewing all articles
Browse latest Browse all 5376

Trending Articles