予選課題: 長い桁数の答えを求める

東京工業大学 SuperCon'98 問題策定委員会
1998.6.1

問題

整数を係数に持つ3次方程式の解(実数根)を、小数点以下400桁まで 求める。問題の方程式を

x3 - 6 x2 + 8 = 0
とすると、この方程式は3つの実数根α, β, γ (α < β < γ) を持つ。ここで、
-2 < α < -1、  1 < β < 2、  5 < γ < 6
である。根β を十進数で小数点以下400桁まで標準出力に書き出す プログラムを作成せよ。なお、小数点部分は横50桁単位で改行すること。

ヒント

問題を解く鍵は3つある。1) 根を近似的に求めるためのアルゴリズムの選択、 2) 長い桁数(多倍長)の計算をどうするのか、3)計算機上で効率よく計算するための 手法の活用、である。以下、それぞれについて簡単なヒントを与える。

1)近似解アルゴリズム

f(x) = x3 - 6 x2 + 8
とすると、f(β)=0である。したがって、ある規則で、xの値を変化させながら、 f(x)=0となるxを求めれば、その答えは β となりゆる。xの値の列を x1 , x2 , ... とすると、
xn+1 = xn - f(xn)/A (A ≠ 0, Aは適当な定数)
が知られている(直感的には A は、この関数のある地点での傾きになっている)。 Aおよびx1 が適切に選べれば、これを無限に繰り返して得られる x が求める β の値である(ニュートン法)。

ただし、これでは永久に計算が終わらないので、適当な精度が得られたところで 計算を打ち切る必要がある。打ち切るための目安としては、

|xn - x| ≦ K(1-ε)n
を利用する。ε に関しては、正定数であって
ε ≦ f'/A ≦ 2 - ε
f' : f の1次微分(= 3 x2 - 12 x) で、 x=xi のときの値
となるように選ぶことで、xが保証される。なお、Kは、1程度の正数。 この場合、A, x1 の選択は、近似の精度と収束の速さに影響する。

Aを、f'で置き換えるアプローチも存在する(ニュートン・ラプソン法)。すなわち、

xn+1 = xn - f(xn)/f'(xn)
f'は直感的には、傾きを表わす。この関係がうまくいくためには、 f'がxの 近傍で連続(f'(x) ≦ 0)であり、かつ、 |x - x1| が十分小さいことが 必要である。

この手法での収束の速度は、

|xn - x| ≦ B exp(C 2n)
で与えられる。ただしB, Cはある定数で、C < 0である。

2) 長い桁数の計算(多倍長計算)

多倍長の足し算 C = A + B を考えてみる。A, B, Cは整数配列とし、それぞれの 値は、配列要素の列で表わすことにする。たとえば、A=123456789123ならば、

A[0]=1234, A[1]=5678, A[2]=9123 (10進数で1要素あたり4桁格納すると仮定)
と表わせる。実際の計算は、
C[i] = A[i] + B[i],   i=N, ..., 0 (Nは最大桁数)
を繰り返しながら、桁上がりが生じるたびに、必要な処理を行えばよい。

引き算は、基本的には足し算と同じである。

掛け算も、通常の掛け算と同じ考え方が使える。ただし、各配列要素同士で 掛け算した結果が、配列要素で表現できる数の範囲を超えてはいけない。 また、要素同士の掛け算の結果が決められた桁数(今の場合4桁)を超えた場合の 処理も必要である。

割り算は、除数が4桁以下の数である時は、直前の要素の計算の余りを考慮することで、 通常の割り算と同じ考え方が使える。しかしながら、多倍長同士の割り算の場合には、 除数の逆数を、被除数に乗じる方が計算速度が速くなる。その場合、正の除数 b を

b = B0(1 - δ)
ただし、B0 は4桁以下の自然数 × 10整数 、  0 < δ < 1、   δ は長桁で表現される数を小数点数以下で表わした数である。
とする。この時、除算 a/bは次のように表わされる。
a/b = a/B0 Πk=0 (1 + δ2k )
ここで
Πk=0 ...
は続く式の 積を意味する。 (計算の都合上、δ2kは (δ2k-1)2 を利用し、 乗積は必要な精度の項まで用いる)

なお、今の場合、10進表現を仮定しているが、2進表現で多倍長計算を行うことも 可能である。

3) 計算速度向上のためのヒント

本問題のように、繰り返し計算がある場合、アルゴリズム上の繰り返し回数を 減らすことが重要である。その一方で、答えに到達するまでの、収束速度も 重要である。また、簡単な掛け算、割り算は、足し算、引き算に置き換えることも 可能である。さらに、除算を除数の逆数で乗じる場合の公式も活用できる。

いまの問題の場合、xn からxn+1を求める場合、 単純に前述の式から計算する こともできるが、例えば次のような形で求めることもできる。

xn+1 = xn2 /6 + 4/3 xn あるいは、
tn+1 = 3/4 tn - 1/8 tn2,   x = 1/t あるいは、
xn+1 = √{(xn3 + 8)/6}
なお、√ の計算には工夫を要する。
また、逆数計算には次の式が利用できる。
1/(1 -δ) = Πk=0 (1 + δ2k),  (|δ| < 1) あるいは、
1/(1 +δ) = (1 - δ)Πk=0 (1 + δ2k),  (|δ| < 1)

参考

小数点以下50桁を示す。

30540728933227860459313349292274081599849729126372

審査のために使用する計算機の int,longのサイズはそれぞれ 32bit,64bitとする。

本選予告

「板詰め問題」 与えられた板を組み合わせて、四角形を埋める。