計算量

ana^nO(logn)O(\log n)で求めることができます。

普通に計算しようとするとaann回かけるので、O(n)O(n)かかります。


仕組み

例として3133^{13}を解いてみましょう。

理由はこれから述べますが繰り返し二乗法ではまず、指数を二進数に変換します。
今回だとn=13n = 13なので

13(10)=1101(2)13_{(10)} = 1101_{(2)}

となりますね。
これをさらに

13(10)=1101(2)=8+4+1=23+22+2013_{(10)} = 1101_{(2)} = 8 + 4 + 1 = 2^3 + 2^2 + 2^0

と変換します。

これを指数に使うと

a13=a8+4+1=a8×a4×a1a^{13} = a^{8+4+1} = a^8 × a^4 × a^1

このようにして2の累乗の形に変換できました。

そして a8×a4×a1a^8 × a^4 × a^1 は、前の値を二乗するだけで求まります。
つまり、二進数化した後にその桁数分ループを回し、ループごとにaaaaをかけていく。1が立っていれば答えに今のaaをかけてあげることで計算量を落としつつ結果を得られるということです。
文字だけ見てもあれなので、この後に載せるコード例を見ると想像つきやすいと思います。

一般に、nnを2進数で表現したときその桁数は log2n+1\lfloor \log_{2}n \rfloor + 1 であり、これがそのままループ数と対応するためnn回の掛け算をlogn\log n回に抑えることができます。

ll power(ll a, ll n) {
  ll result = 1;
  while (n > 0) {
    // nの最下位ビットが1ならresultに掛ける
    if (n & 1) result *= a;
    a *= a;
    // n を右シフトして次のビットへ
    n >>= 1;
  }
  return result;
}

実際にはaaが大きな数になってしまうためmodmodを取るような問題が多いです。
掛けるたびにmodmodを取ってあげればいいですね(これは頻出テクニックです。知らなかった人は先にmodmodのテクニックについて調べてください)。


例題

以下の例題を解いてみましょう。

問題文
aba^bを1000000007で割った余りを求めてください。


制約
1a991 \leq a \leq 99
1b1091 \leq b \leq 10^9

bbが最大10910^9なので、普通にO(n)O(n)で計算しようとするとTLEします。繰り返し二乗法でO(logb)O(\log b)に落としましょう。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const ll MOD = 1000000007;

ll power(ll a, ll n, ll mod) {
  ll result = 1;
  a %= mod;
  while (n > 0) {
    if (n & 1) result = result * a % mod;
    a = a * a % mod;
    n >>= 1;
  }
  return result;
}

int main() {
  ll a, b;
  cin >> a >> b;
  cout << power(a, b, MOD) << endl;
  return 0;
}

掛け算をするたびに% modを取っています。result * aの前にresultは既にmod未満なので、オーバーフローを防ぐためにはamod未満であることが必要です。そのため最初にa %= modとしています。


その他の例題

  1. AIZU ONLINE JUDGE AOJ - NTL_1 Power
  2. 競技プログラミングの鉄則 演習問題集 - A29 - Power

まとめ

指数が大きいときの累乗計算は繰り返し二乗法が基本です。
難しい内容でもなくこのアルゴリズムだけで解けるような問題だとAtCoderではB、C辺りで頻出なので、オーバーフローを起こして爆死することのないよう知っておくといいでしょう。
もしくはpythonを使いましょう(メモリが許す限り桁が無限なので)。