今度はプログラミングの話しです。
(x+y+z)(1/x+1/y+1/z)=n
x, y, z, n∈N
上記を満たす、x, y, z, nを列挙するプログラムを作るのだが、どうするのが良いのか。
例えば、nを与えて、x, y, zを出力するとして、必ず見つかるものなのだろうか?
プログラミング言語であるから、変数の取り得る範囲があって、その有限の中で見つかるものだろうか。
先の数学の話しの中でも登場したが、
x≦y≦z
gcd(x, y, z)=1
という条件を付け加える。
さすれば、
x≦y≦z<fin
のようなfinを与えることも出来る。
これが妥当だろうか。
fin=10のとき、7個
fin=100のとき、21個
fin=1000のとき、46個
…
この少なさです。
高速化を目指すのであれば、画期的な方法を見つける必要がありそうですね。
まぁ、そんな簡単にみつかるとは思えない。
まずはたたき台。
x, y, zの3重ループになるのだが、yをx, zで挟む形で、一番内側に持ってくるだろう。
for (z=1; z<fin; z++) {
for (x=1; x<=z; x++) {
xz = (x+z)*x*z;
for (y=x; y<=z; y++) {
if ( xz%y ) continue;
u = (x+y+z)*(x*y+x*z+y*z);
l = x*y*z;
if ( u%l > 0 ) continue;
printf("%d\t%d\t%d\t%d\n", u/l, x, y, z);
}
}
}
こんな感じ。
まぁ、zが大きくなるにつれ、なかなか新しい答えが出てこないというものだから、あえてgcdを取らないで出力させてた。
しかし、x=y=zが毎回出てくるのもなんなんで、
for (z=1; z<fin; z++) {
for (x=1; x<z; x++) {
xz = (x+z)*x*z;
for (y=x+1; y<z; y++) {
if ( xz%y ) continue;
u = (x+y+z)*(x*y+x*z+y*z);
l = x*y*z;
if ( u%l > 0 ) continue;
printf("%d\t%d\t%d\t%d\n", u/l, x, y, z);
}
}
}
と=を抜いても良いだろう。
それによって弾かれるのは、導入問題でやった、
n=9, x=1, y=1, z=1
n=10, x=1, y=1, z=2
n=10, x=1, y=2, z=2
だけである。
さて、数学で考えたなかに、
x1:z1=x2:z2
と整数比が等しい組(x1, y1, z1), (x2, y2, z2)は、
外項の積と内項の積は等しいより、
x1・z2=x2・z1
となり、さらに
x1・z2=x2・z1=y1・y2
となります。
n=1のとき、(x, y, z)=(1, 1, 1)
と1つしかないケースも、上記の式は成り立つので、
y1とy2の小さな方だけをプログラムで見つけ、
もう一方は別のプログラムで計算させるという方法もある。
安直に、変数cをカウンターとして、
for (z=1; z<fin; z++) {
for (x=1; x<z; x++) {
xz = (x+z)*x*z;
for (c=0, y=x; c<1 && y<z; y++) {
if ( xz%y ) continue;
u = (x+y+z)*(x*y+x*z+y*z);
l = x*y*z;
if ( u%l > 0 ) continue;
printf("%d\t%d\t%d\t%d\n", u/l, x, y, z);
c++;
}
}
}
とやってしまいたいところでもある。
ただ、すべての(x, z)の間に、yがあるかというと、無い場合が殆どであるから、枝刈りとしては不十分だろうか。
y1≦y2として、イコールは重解であり、重解以外は大小関係が存在する。
重解の場合は、(x, y, z)が等しいので、sqrt(x*z)=yであり、
for (z=1; z<fin; z++) {
for (x=1; x<z; x++) {
xz = (x+z)*x*z;
sq = sqrt(x*z)+0.5;
for (c=0, y=x; c<1 && y<sq; y++) {
if ( xz%y ) continue;
u = (x+y+z)*(x*y+x*z+y*z);
l = x*y*z;
if ( u%l > 0 ) continue;
printf("%d\t%d\t%d\t%d\n", u/l, x, y, z);
c++;
}
}
}
とすれば、多少は高速に動くだろうか。
yの片割れをプログラミングでやろうとすると、小数を扱ってやることになるのだろうか。
あんまりよろしく無いな。
そっちの方も考えなきゃね。
ではでは