【C++】2つの数の公約数の個数を効率的に求めるプログラム
この記事では、2つの数に共通する約数(公約数)がいくつあるかを数える方法を解説します。すべての公約数を実際に列挙するのではなく、その「個数」だけを効率的に求めることが目的です。
例えば、12と24という2つの数を考えてみましょう。12と24の公約数は、1、2、3、4、6、12の6つです。したがって、答えは6となります。
アルゴリズムの考え方
すべての公約数を1つずつ調べるのは非効率です。ここで重要なのが、「2つの数aとbの公約数は、必ずgcd(a, b)(最大公約数)の約数になる」という性質です。つまり、gcd(a, b)の約数の個数を数えれば、それがそのまま公約数の個数になります。
さらに、約数の個数を数える際、1からgcdまで順番に調べる必要はありません。√gcd まで調べれば十分です。i が gcd の約数であれば、gcd / i もまた約数になるためです。これにより計算量を大幅に削減できます。
countCommonDivisor(a, b) の手順
begin
count := 0
gcd := aとbの最大公約数
for i := 1 to √gcd, do
if gcd が i で割り切れる, then
if gcd / i = i, then
count := count + 1
else
count := count + 2
end if
end if
done
return count
end
i が約数のとき、gcd / i も約数であるため、基本はカウントを2増やします。ただし、i が √gcd と一致する場合(gcdが完全平方数の場合)、同じ約数を二重に数えてしまうため、カウントは1だけ増やします。
C++での実装例
#include<iostream>
#include<cmath>
using namespace std;
int gcd(int a, int b) {
if (a == 0)
return b;
return gcd(b % a, a); // ユークリッドの互除法
}
int countCommonDivisors(int a, int b) {
int gcd_val = gcd(a, b); // aとbの最大公約数を取得
int count = 0;
for (int i = 1; i <= sqrt(gcd_val); i++) {
if (gcd_val % i == 0) { // iがgcdの約数の場合
if (gcd_val / i == i) // 重複カウントを避ける
count += 1;
else
count += 2;
}
}
return count;
}
int main() {
int a = 12, b = 24;
cout << "Total common divisors: " << countCommonDivisors(a, b);
}
実行結果
Total common divisors: 6
計算量の評価
このアルゴリズムでは、ユークリッドの互除法によるGCD計算が O(log(min(a, b)))、約数の個数のカウントが O(√gcd(a, b)) かかります。小さい方の数まで全て調べる O(min(a, b)) の素朴なアプローチと比べ、大きな数を扱う場合でも高速に動作するのが大きな利点です。
-
C++で2本の直線の交点を求めるプログラムの書き方
直線ABを定義する2点A・Bと、直線CDを定義する2点C・Dが与えられたとき、この2つの直線の交点を求めるのが課題です。 注意 − すべての点は、X座標とY座標を持つ2次元平面上にあるものとします。 図では、A(a1, a2)とB(b1, b2)を通る直線、C(c1, c2)とD(d1, d2)を通る直線という、互いに異なる2つの直線が描かれており、P(p1, p2)がその交点を表しています。 交点の求め方 まず、2点を通る直線を「ax + by = c」の形の方程式で表します。各点の座標を使って、次のように係数を計算します。 A1 = b2 - a2 B1 = a1 - b1 C1 =
-
Pythonで2つの数の公約数を求めるプログラムの書き方
はじめに この記事では、以下の問題文に対する解決方法について学んでいきます。 問題文 2つの整数が与えられたとき、それらに共通する約数(公約数)の個数を表示する必要があります。 アプローチの考え方 まず、入力として受け取った2つの数のうち、小さい方の値(最小値)を計算します。続いて、1からその最小値までの各値で2つの数を順番に割っていき、両方の数を割り切ることができるかどうかをループ処理で確認します。 条件が真(True)と評価されるたびに、カウンターを1ずつ増加させます。最終的なカウンターの値が、2つの数の公約数の個数となります。 実装例 それでは、以下のコードで実際の実装を見てみましょう。