連続二乗法の証明
📂整数論連続二乗法の証明
アルゴリズム
自然数 a,k,m に対して b≡ak(modm) を次のように計算できる。
ステップ 1. k の2進展開
ui=0 又は ui=1 に対して次のように表す。
k=i=0∑rui2i=u0+2u1+⋯+2rur
ステップ 2.
a2r≡(a2r−1)2≡Ar−12≡Ar(modm) を以下のように計算する。
aa2a4a8≡(a1)2≡(a2)2≡(a4)2≡A02≡A12≡A22≡A0(modm)≡A1(modm)≡A2(modm)≡A3(modm)⋮
ステップ 3.
A0u0⋅A1u1⋅⋯Arur を計算すると次の結果が得られる。
ak≡A0u0⋅A1u1⋅⋯Arur(modm)
説明
コンピュータの発展によりべき乗の計算も速くできる時代が来たが、人間は満足を知らない。連続べき乗法はモジュラ演算において、非常に大きな数を直接計算することなくその答えを得る方法だ。一度べき乗するたびに(modm) で割っていくために、数がm 以下に落ちて、計算量が減るのだ。
例
例えば、7327(mod853) を計算するとしよう。7327 に常用対数を取ると327log7≈327⋅0.8450=276.315 であり、桁数だけで 277 の大きな数だ。正直に全部掛けて割り算するには大きすぎるから、上のアルゴリズムを使ってみよう。まず上のアルゴリズム通りに327 を2進展開すると以下のようになる。
327=256+64+4+2+1=28+26+22+21+20
ステップ2通りに計算してみると
772747871673276471287256≡(71)2≡(72)2≡(74)2≡(78)2≡(716)2≡(732)2≡(764)2≡(7128)2≡7≡72≡492≡6952≡2272≡3492≡6752≡1232≡6282≡7(mod853)≡49(mod853)≡2401≡695(mod853)≡227(mod853)≡349(mod853)≡675(mod853)≡123(mod853)≡628(mod853)≡298(mod853)
したがって
7327=7256⋅764⋅74⋅72⋅71=298⋅123⋅695⋅49⋅7≡286(mod853)
この方法も大変と感じるかもしれないが、ただ327 回を一つずつ乗算するよりは、とても計算量が少ない。
証明
ak==≡au0+2u1+⋯+2rurau0a2u1⋯a2rurA0u0A1u1⋯Arur(modm)
■
コード
以下は、7327(mod853) を連続べき乗法で計算する例のコードで、R言語で書かれている。注目すべき点は、power
オプションは負の整数にも対応し、mod
が素数ならpower=-1
を入力することで、与えられたbase
の乗算に対する逆元を求めることができる。
FPM<-function(base,power,mod)
{
i<-0
if (power<0) {
while((base*i)%%mod != 1) {i=i+1}
base<-i
power<-(-power)}
if (power==0) {return(1)}
if (power==1) {return(base%%mod)}
n<-0
while(power>=2^n) {n=n+1}
A<-rep(1,n)
A[1]=base
for(i in 1:(n-1)) {A[i+1]=(A[i]^2)%%mod}
for(i in n:1) {
if(power>=2^(i-1)) {power=power-2^(i-1)}
else {A[i]=1} }
for(i in 2:n) {A[1]=(A[1]*A[i])%%mod}
return(A[1])
}
FPM(7,327,853)
FPM(7,-1,11)