いきなりですが問題です.
を計算しなさい.
例の解法(その1) - わさっきの続編です.今期の試験問題の一つで,こちらの出題の方が先でした.本日も,アルゴリズム名は書きません.
手計算で求めるための,表をつくります.初期値は,こうです.
使用する変数は,,,の3つで,の初期値は必ず1,の初期値はべき乗の底,は指数です.法となる29については,値は変わらないので表に現れません.
アルゴリズムに従うと,行単位で,,の順に新しい値を書いていきますが,先にの変化を求めておきます.というのも,やの変化に依存せずに計算でき,また,正当な方法で何回ループすれば計算が終了するかを,先に知ることができるからです.
具体的には,2で割っていき,端数は捨てて,0になるまで計算します.0になったら,表はそこまでなので,表の底部の横線も引きます.
の初期値が十分に大きいとき,の列の最後の3つは,「2,1,0」または「3,1,0」のどちらかになります.単純ミスを減らすのに有用です.
次はです.これもまた,やの変化に依存せずに計算できます.2行目以降のの値を求めるためのルールは,以下のとおりです.
値 = 1つ上の値法
上に書いたとおり,この問題では法は29で固定です.具体的なの値ですが,
- 2行目は, = = 23
- 3行目は, = = 7
- 4行目は, = = 20
- 5行目は, = = 23
6行目,すなわちになるときのの値は不要なので計算しません.表は次のようになります.
最後に,の計算です.ただしこの列は,すべてのマスで計算するわけではありません.計算をしない行というのは,
1つ上のtが偶数のとき
です.先に,該当箇所に「↓」を書いておきましょう.
の空きマスの値は,次のルールで,地道に,ミスすることなく計算する必要があります.
値 = 直前のの値 × 1つ上のの値 法
1の2行下の空白は,1×23で,これは29で割っても余りは変わりませんので,23を格納します.の値を最初に更新するときは,「1つ上のの値」と言ってもいいでしょう.
23の2行下の空白は, = = 25です.
最後の行は, = = 24となります.
この24が,求めるべき,の値となります*1.めでたしめでたし.
なのですが,計算ミスへの対策を,もう少し考えてみましょう.今回は先日のような,行単位で検算に便利な等式があるわけではなく,1箇所で間違えると,下の行がすべて間違いになってしまい,それに気づきにくいおそれがあります.
基本的な表チェックの方法は,次のとおりです.
- の列は,真に単調に減少します.最後の3つは「2,1,0」または「3,1,0」のどちらかです.
- の最後の行が「↓」になることはなく,そこでは必ず計算を行います.
- との列に出現する数値は,法(この問題では29)未満です.
- の列の値に関して,最初の行を取り除き,値が変更された箇所を1,値が変更されなかった箇所(「↓」と書いた箇所)を0に置き換え,最下段から上にあがる順にビット列をたどると,指数の2進数表現と一致します.この問題での1と0の置き換えは,最下段から上にあがる順に,変更あり(1),変更あり(1),変更なし(0),変更あり(1),変更なし(0)で,11010は10進数の26のことです.
最後の項目は,この計算の正当性を示す等式(関係式)から導くことができます.を計算する際,表の値は以下のようになります.
行目のの値 =
行目のの値 = .ただし
は「(の乗)の乗」ではなく(それは = です),「の(の乗)乗」です.すなわちべき乗演算は,C言語でいう右結合の演算である点に注意が必要です.
の値は,最初は底,そして,,,…をそれぞれ法で割った値となります.そして,はそこからを計算するのに必要な値だけを取り出して,掛け算し,で割った余りを求めているということです.
といった,動作原理に基づくチェック方法では,不満のある人のために,よく使う裏技を一つ,書いておきましょう.剰余が絡む積についての,興味深い等式があります*2.証明は省略します.
法に近い(したがって,少々大きな)2つの数を掛け算して,で割った余りを求めるとき,2つの数をそれぞれ「からその数を引いた値」に変更してよい,というルールです.
これを使うと,例えばの列で,23の次が7になるところは,,を割り当てるととなり,これを29で割ったら余りは7です. = = 7として計算する方法に比べて,ずいぶんと簡単になります*3.
の最後の値を求めるのは, = = 24です.
うまく使うと,乗算の手計算の手間を大きく減らせますが,その代わり,「からその数を引いた値」のところで間違えやすいので,これに頼りすぎないようにしましょう.検算のツールとするのがいいと思います.