C++で2^(2^A) % Bを効率的に計算する方法
このチュートリアルでは、2^(2^A) % Bという式の値を求めるプログラムをC++で作成していきます。
一見すると巨大な指数計算が必要に思えますが、再帰関数を使うことで、実際に巨大な数を計算することなく効率的に答えを求められます。ここでは、その考え方と実装手順を順番に解説します。
解き方の手順
この問題は、次のような性質を利用して再帰的に解くことができます。
A と B の2つの引数を受け取る再帰関数を作成します。
A が 1 の場合、2^(2^1) % B = 4 % B となるため、4 % B を返します(ベースケース)。
それ以外の場合は、引数を A - 1 として関数を再帰的に呼び出します。
得られた結果に対して「result * result % B」を計算して返します。これは (x^2) % B を意味し、指数を1段階ずつ戻しながら値を構築していきます。
最終的な結果を出力します。
なぜこの方法でうまくいくのか
2^(2^A) は A が大きくなると天文学的な桁数になるため、直接計算するのは現実的ではありません。しかし、モジュロ演算には (x * y) % B = ((x % B) * (y % B)) % B という重要な性質があります。この性質により、各段階で剰余を取りながら計算を進めることで、オーバーフローを避けつつ正確な答えを得ることができます。
サンプルコード
それでは、実際のコードを見てみましょう。
#include <bits/stdc++.h>
using namespace std;
long long solveTheEquation(long long A, long long B) {
// 2^(2^1) % B = 4 % B
if (A == 1) {
return (4 % B);
}
else {
long long result = solveTheEquation(A - 1, B);
return result * result % B;
}
}
int main() {
long long A = 37, B = 467;
cout << solveTheEquation(A, B) << endl;
return 0;
}実行結果
上記のコードを実行すると、次の出力が得られます。
113
A = 37、B = 467 の場合、2^(2^37) % 467 の計算結果は 113 となります。このように、膨大な指数を持つ式でも再帰とモジュロ演算を組み合わせれば、瞬時に答えを求められるのです。
まとめ
本記事では、再帰関数とモジュロ演算の性質を活用して、2^(2^A) % B を効率的に計算する方法を紹介しました。このテクニックは競技プログラミングなどでも頻繁に登場するので、ぜひマスターしておきましょう。チュートリアルについて質問がある場合は、コメント欄でお気軽にお尋ねください。
-
C++で三角形の周囲の長さ(外周)を求める方法
この記事では、三角形の周囲の長さ(外周)とは何か、三角形の種類ごとの周囲の長さの公式、そしてC++でそれらを求めるプログラムの書き方について詳しく解説します。周囲の長さ(Perimeter)とは周囲の長さとは、図形の外側を1周したときの総距離のことです。基本的には、図形を構成するすべての辺の長さを足し合わせたものになります。三角形の周囲の長さ三角形は3つの辺を持つ図形であるため、その周囲の長さは3辺の長さの合計として求められます。公式:周囲の長さ = すべての辺の合計周囲の長さ = x + y + z三角形の周囲の長さを求めるC++プログラムサンプルコード#include <iostre
-
C++で二分木の重複する部分木を検出する方法
問題の概要二分木が与えられたとき、その中に存在する重複する部分木(duplicate subtrees)をすべて見つける問題を考えてみましょう。ここでいう「重複」とは、構造とノードの値が完全に一致する部分木が2つ以上存在することを意味します。各種類の重複部分木について、代表としてどれか1つの根ノードを返せばよいことになっています。たとえば、次のような二分木があるとします。この木に含まれる重複する部分木は、以下の2つです。値 4 を持つ単一ノードの部分木(2か所に出現)根が 2 で、子に 4 を持つ部分木(2か所に出現)解法のアプローチ:部分木のシリアライズこの問題を効率的に解く鍵となるのは、部