C++
 Computer >> コンピューター >  >> プログラミング >> C++

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を直接探索する必要がないため、非常にシンプルかつ高速な解法となります。

  1. C++ですべての部分配列から最小のLCMとGCDを求める方法

    サイズNの正の整数からなる配列 arr が与えられたとき、考えられるすべての部分配列の中で最小のLCM(最小公倍数)とGCD(最大公約数)を求める問題を考えてみましょう。例えば、配列が {2, 66, 14, 521} である場合、最小のLCMは 2、最小のGCDは 1 となります。解き方のアプローチこの問題は貪欲法(グリーディーアプローチ)を用いて効率的に解くことができます。ポイントは次の2点です。部分配列に含まれる要素数を減らすほど、LCMは小さくなる傾向があります。逆に、部分配列のサイズを大きくするほど、GCDは小さくなります。したがって、求めるべき最小のLCMは「配列内の最小の要素」(

  2. 【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 で割り切れ、範囲