以下のために私たちは知っている、p個の評価(P> 0)、簡単な累乗アルゴリズムは、再帰的な方法を使用して、ベース番号は、結果として乗法指数p倍程度です。指数pはアルゴリズムが複雑で、現在のマシンがまだ計算に多くの時間を過ごすには線形である時間を持っている場合でも、(> 1E7)が大きい場合、このアルゴリズムの時間計算量は、O(P)です。
電力は、ナイーブなアルゴリズムのために必要とされる改善され、パーティションへの効率的な方法である:pが偶数である場合、直接P(にP / 2)*(P / 2の二つの部分で)、そして各A P / 2だけでなく、それがパワーになるまで、除算を行うには継続する; pが奇数の場合、我々はAを提案し、その後、残りのP-1は、前の状況に戻った、デュアル指数形になり、インデックスが0であります、それは簡単に結果が1であることを主張することができます。最後に、各ステップの分離結果をマージとすることができます。したがって、我々は、再帰的な数式を記述することができます。
インデックスp = 18,446,744,073,709,551,616は、わずか64回の乗算が計算される場合、例えば、結果として導出することができると比較して、パーティションソリューションO(対数P)の時間計算量は、線形複雑度の点で結果が大幅に改善されています。
このアルゴリズムのDOを実装する方法?大きな演算結果のために、高精度なアナログ演算が考慮されるべきであることを注意、またはこのアルゴリズムモジュロmの終了を検討してください。最初にこの問題に対処する再帰的に考えます。
typedefの長い 長いLL。 LL fspow(LL A、LL P){ 場合(P == 0 ) リターン 1 。 もし(P&1 ){ LL T = fspow(P- 1 )。 リターントン* ; } 他{ LL T = fspow(P / 2 )。 リターン T * T ; } }
多くの人々が非効率的と考えられ、再帰的、直感を再帰的に競合しています。実際には限らない場合。私たちは、時間の関数呼び出しのオーバーヘッドは、主に二つの側面に反映されている知っている:1、コールスタックは、高レイテンシのメモリアクセス命令によって実装される必要があり、関数のパラメータ、ローカル変数、リターンアドレスやその他の情報を、保存されます; 2、分岐命令をこのような原因による洗掘にパイプラインの故障等の分岐予測として、追加のオーバーヘッドが生じます。
データサイズが得られたアルゴリズムの誤っ元O(対数P)アルゴリズム書かれた生きている廃棄物O(P)に比べて大きい場合には、実際には、基礎となるシステムによって引き起こされるこれらのコストは無視できる程度であります。あなたは非常に限られた資源システムに直面している場合を除き、またはあなたはカードデータの制限最適化したい、または時間再帰呼び出しを費やして気にしないでください。もちろん、それは再帰的空間的複雑考慮されなければなりません。
再帰的アルゴリズムは、成長すると、スタック領域を占有し、これは我々が見たくないものです。かどうかが保たれ、シンプルでエレガントなだけではありませんが、また、それを高速に一定の電力アルゴリズムスペースの複雑さを持っていますか?
これは、高速電力アルゴリズムの非再帰的なバージョンです。コードの次の2行は、極端にコアに集中されてきました。
1 のための(S = 1; P; P / = 2、A = A * ) 2 であれば(P&1)S = S *。
塩基数であり、pは、インデックス、アルゴリズムが終了すると、S =であるP。
アルゴリズムの原理で見てみましょう。アイデアはまだ私達の前の議論と一致して分割統治です、違いはもはや再帰的に解決されません。
エッセンス「分」は、インデックスが偶数でなければなりませんバイナリインデックスです。インデックスは同じパワーの結果を作るために、半分にすると、塩基数は、正方形である必要があります。形式的な記述。指標P / 2だけでなく、P / 4 P / 8 ...... 1に分割され続け 、 塩基数は、常に疲れを乗じました。インデックスは1になり、その結果、必要な基本番号です。インデックスが偶数でない場合、塩基番号の最初の解体は、残りの電力は、その後、上記の方法を扱うことができ、さらに消費電力です。
コードには、いくつかのヒントが含まれます。
1.分割オペレータの使用は/機能を切り捨てています。指数pは奇数である場合、P / 2の結果は、実質的に、我々は、Pから1を引いた塩基手間を必要とするとき排除が取り除かれ、P-1/2に等しいです。除数が2であるため、実際には、また、本質的にバイナリ分割を使用して、P >> = 1を書き込むことができます。
2.当社は、%演算子のオーバーヘッドがpのパリティ、p個のバイナリが直接最下位ビットを決定する場所だけで判断するために、偉大であることを知っています。
具体的な用途
多くの場面での電源操作は、重要なアプリケーションを持っています。例えばRSA非対称暗号化アルゴリズム、以下の式で平文を暗号化:
C iは、 M = I E mod nをを
前記公開鍵ペアのプレーンテキスト、(E、N)に関連付けられたCI、MI値暗号文。
そして、以下の式により暗号文を解読します:
M I = Cがiはdの MOD Nを
Miは、プレーンテキストに関連付けられた値であり、(D、n)は秘密鍵ペアです。
私たちは、暗号化や復号化の両方が、累乗及びモジュラー算術演算で使用することがわかります。これは、上記の私たちの速い累乗が有用団体です。
RSA、彼らは次の式のダウンに起因していると、フォームの他のタイプ、しばしば使用より:
A P MOD A
累乗結果を法とするので、最終的な結果は以下であり、kに等しいです。我々の高速電力アルゴリズムを見て中間結果は、基本データ型の範囲を超えた場合、中間結果は、おそらくkよりもはるかに大きいだけでなく、高精度なアナログ演算することで、不要と時間の無駄です。上記だから、高速電力アルゴリズム、最適化の余地があります。
数論が指摘、(A * B)は、k = MOD(A MODのK)*(B kのMOD)MODのK。2つの数の積、すなわち、再び法として、2つの数字が等しい次いで乗算モジュロ、及び弾性率です。この性質を利用して、我々はできるA P変形MOD K当量(A MOD K)P、MOD K乗算を実行するたびに、最初にこの性質を利用して乗算器を減少させ、そして次いで乗算されます。
コードが変更されます
1%= K。 2 ため(= 1秒; P; P / = 2、A =(*)%のK)が 3 であれば(P&1)S =(S *)%のK。
ここで、P、Kの意味は、上記と一致しね。
これは、kの速いべき乗剰余演算のための非再帰的なアルゴリズムです。