C++でX = P*A + Q*Bを満たす最小の正整数Xを求める方法
問題文
AとBの値が与えられたとき、次の式を満たす最小の正整数Xを求めることを考えます。
X = P*A + Q*B
ここで、PとQは「0または任意の正・負の整数」を取ることができます。つまり、AとBをそれぞれ何倍かして足し合わせた結果の中から、最も小さい正の整数を見つける問題です。
例
A = 2、B = 4 の場合、答えは 2 になります。
たとえば P = 1、Q = 0 とすると X = 2*1 + 4*0 = 2 となり、これより小さい正の整数は作れないため、答えは2です。
アルゴリズム
この問題は、ベズーの等式(Bézout's identity)と呼ばれる数論の定理を使うことで解くことができます。
- ベズーの等式によると、X = P*A + Q*B の形で表せる最小の正整数は、必ず A と B の最大公約数(GCD)に一致します。
- したがって、PやQを総当たりで探す必要はなく、AとBのGCDを計算するだけで答えが得られます。
GCDの計算には、効率的な手法として知られるユークリッドの互除法を使用します。
実装例(C++)
#include <iostream>
using namespace std;
int getGcd(int a, int b) {
if (a == 0) {
return b;
}
return getGcd(b % a, a);
}
int main() {
cout << "Answer = " << getGcd(2, 4) << endl;
return 0;
}実行結果
上記のプログラムをコンパイルして実行すると、次の出力が得られます。
Answer = 2
まとめ
X = P*A + Q*B を満たす最小の正整数Xは、AとBの最大公約数に等しいという性質を利用すれば、ユークリッドの互除法によって O(log(min(A, B))) の計算量で効率的に求められます。PとQを直接探索する必要がないため、非常にシンプルかつ高速な解法となります。
-
C++ですべての部分配列から最小のLCMとGCDを求める方法
サイズNの正の整数からなる配列 arr が与えられたとき、考えられるすべての部分配列の中で最小のLCM(最小公倍数)とGCD(最大公約数)を求める問題を考えてみましょう。例えば、配列が {2, 66, 14, 521} である場合、最小のLCMは 2、最小のGCDは 1 となります。解き方のアプローチこの問題は貪欲法(グリーディーアプローチ)を用いて効率的に解くことができます。ポイントは次の2点です。部分配列に含まれる要素数を減らすほど、LCMは小さくなる傾向があります。逆に、部分配列のサイズを大きくするほど、GCDは小さくなります。したがって、求めるべき最小のLCMは「配列内の最小の要素」(
-
【C++】Cで割り切れ、範囲[A, B]に含まれない最小の正の整数を求める方法
問題の概要今回は興味深いプログラミング問題を取り上げます。3つの整数 A、B、C が与えられたとき、「X mod C = 0」を満たし、かつ X が範囲 [A, B] に含まれない最小の正の整数 X を求めることを考えます。例えば、A = 5、B = 10、C = 4 の場合、答えとなる X の値は 4 です。これは、4 が C で割り切れ(4 ÷ 4 = 1)、かつ範囲 [5, 10] の外側に存在するためです。解法のアプローチこの問題は、以下のシンプルな手順で解くことができます。C が範囲 [A, B] に含まれない場合: C をそのまま結果として返します。C 自身が「C で割り切れ、範囲