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

C++で配列のGCD(最大公約数)を1にする変換アルゴリズム

このチュートリアルでは、配列全体のGCD(最大公約数)が1になるように配列を変換するプログラムをC++で解説します。

問題の概要

ここでは、配列と正整数 k が与えられます。許される操作は「配列の要素を k で割る」ことだけで、この操作は各要素が k 未満になるまで何度でも繰り返し行えます。この操作のみを使って、すべての要素のGCDを1にできるかどうかを判定するのが課題です。

アプローチのポイント

鍵となるのは「k の素因数はすべて k 以下である」という性質です。要素を k で割って取り除けるのは k の素因数だけなので、k より大きい素因数はどれだけ操作を繰り返しても消すことができません。

したがって、次の手順で判定できます。

  1. 配列全体のGCDを計算する。
  2. そのGCDを素因数分解し、最大の素因数を求める。
  3. 最大の素因数が k 以下であれば "Yes"(GCDを1にできる)、そうでなければ "No"。

C++での実装例

#include <bits/stdc++.h>
using namespace std;
// 配列のGCDを計算する
int calculate_gcd(int* arr, int n){
    int gcd = arr[0];
    for (int i = 1; i < n; i++)
        gcd = __gcd(arr[i], gcd);
    return gcd;
}
// 操作が可能かどうかを判定する
bool convertGcd(int* arr, int n, int k){
    int gcd = calculate_gcd(arr, n);
    int max_prime = 1;
    for (int i = 2; i <= sqrt(gcd); i++) {
        while (gcd % i == 0) {
            gcd /= i;
            max_prime = max(max_prime, i);
        }
    }
    max_prime = max(max_prime, gcd);
    return (max_prime <= k);
}
int main(){
    int arr[] = { 10, 15, 30 };
    int k = 6;
    int n = sizeof(arr) / sizeof(arr[0]);
    if (convertGcd(arr, n, k) == true)
        cout << "Yes";
    else
        cout << "No";
    return 0;
}

出力

Yes

コードの解説

calculate_gcd 関数

標準ライブラリの __gcd を使い、配列の先頭要素を初期値として順番にGCDを更新していき、配列全体のGCDを求めます。

convertGcd 関数

まず配列全体のGCDを取得し、2から√GCDまで順に試し割りして素因数分解を行います。見つかった素因数のうち最大のものを max_prime として記録し、最後に残った商も候補として比較します。そして max_prime <= k が成り立てば true を返します。

main 関数

サンプルとして配列 {10, 15, 30} と k = 6 を使用しています。配列のGCDは5であり、その最大素因数は5で k = 6 以下のため、"Yes" が出力されます。

計算量

GCDの計算には O(n log max(arr))、素因数分解には O(√GCD) かかるため、全体の計算量は O(n log max(arr) + √GCD) となります。要素数や値が大きい場合でも効率的に動作する実装です。

  1. C++でKの倍数間にある配列要素をソートする方法

    配列Aと整数Kが与えられたとき、Kの倍数と次の倍数の「間」に挟まれた要素だけをソートすることを考えます。例えば、配列Aが [2, 13, 3, 1, 21, 7, 8, 13, 12]、K = 2 の場合、期待される出力は [2, 1, 3, 7, 13, 21, 8, 13, 12] です。ここで2の倍数は 2・8・12 の3つです。最初の倍数2と次の倍数8の間にある 13, 3, 1, 21, 7 は昇順に並べ替えて 1, 3, 7, 13, 21 とし、8と12の間には要素13しかないため、すでに整列済みとしてそのまま残します。 アルゴリズムの考え方 配列を先頭から順に走査し、Kの倍数

  2. C++で配列の合計を偶数にするために追加する最小の数を求める方法

    ある数値が格納された配列があるとします。この配列の要素の合計を偶数にするために、最小でいくつの数を追加する必要があるかを求めるのが本記事の目的です。ただし、追加する数は0より大きい正の整数でなければなりません。ルールはシンプルです。要素の合計が奇数の場合は1を追加すれば偶数になります。一方、合計がすでに偶数である場合は、0を追加することが許されていないため、最小の正の偶数である2を追加することになります。アルゴリズムaddMinNumber(arr)begin s := 0 for each element e from arr, do s := e + s