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

C++で方程式を満たす6つ組の数を求める方法を解説

この記事では、方程式を満たす6つ組(セクステュプレット)の個数を求めるアルゴリズムについて解説します。例として、次の方程式を満たす a、b、c、d、e、f の組み合わせがいくつ存在するかを求める問題を取り上げます。

( a + b + c ) * e / d = f

まず、この式を次のように変形してみましょう。

( a + b + c ) = ( f * d ) / e

入力例と出力例

入力 : arr [ ] = { 1, 3 }
出力 : 4
説明 :
 ・( a, b, c, e, f ) = 1、d = 3
 ・( a, b, c, d, e ) = 1、f = 3
 ・( a, b, c ) = 1、( d, e, f ) = 3
 ・( a, b, c, d, f ) = 3、e = 1

入力 : arr [ ] = { 2, 5 }
出力 : 3

解法のアプローチ

ここでは、シンプルで分かりやすい「素朴なアプローチ(Naive Approach)」を用いて問題を解きます。

素朴なアプローチの考え方

式の左辺(LHS)と右辺(RHS)に注目するのがポイントです。

左辺については、( a + b + c ) のすべての組み合わせの計算結果を配列に格納します。同様に、右辺についても ( f * d ) / e のすべての組み合わせの計算結果を別の配列に格納します。

その後、両方の配列をソートして突き合わせ、一致する値が見つかるたびにカウントを増やしていき、最終的な件数を出力します。

C++による実装例

#include<bits/stdc++.h>
using namespace std;
int findsamenumbers(int *arr1, int *arr2, int n){
    int i = 0, j = 0, k = 0, count=0;
    while(( i < n*n*n+1) && (j < n*n*n+1)){
        if(arr1[i] < arr2[j])
            i++;
        else if(arr1[i] == arr2[j]){
            count++;
        int temp = arr1[i];
        while(temp==arr1[++i]){
            count++;
        }
        while(temp==arr2[++j]){
            count++;
        }
    }
    else
        j++;
    }  
    return count;
}
int main(){
    int arr[] = {2,5};
    int n = sizeof(arr)/sizeof(arr[0]);
    // 左辺(LHS)の全パターンを生成
    int index = 0,i;
    int LHS[n*n*n ];
    for ( i = 0; i < n; i++){
        for (int j = 0; j < n; j++){
            for(int k = 0; k < n; k++){
                LHS[index++] = (arr[i] * arr[j]) / arr[k];
            }
        }
    }
    // 右辺(RHS)の全パターンを生成
    int RHS[n*n*n ];
    index=0;
    for (int i = 0; i < n; i++){
        for (int j = 0; j < n; j++){
            for (int k = 0; k < n; k++){
                RHS[index++] = (arr[i] + arr[j] + arr[k]);
            }
        }
    }
    sort(RHS, RHS + (n*n*n));
    sort(LHS, LHS + (n*n*n));
    int result = findsamenumbers(LHS, RHS, n);
    cout<<"方程式を満たす6つ組の数: "<<result;
    return 0;
}

実行結果

方程式を満たす6つ組の数: 3

プログラムの解説

このプログラムでは、左辺と右辺のすべての計算結果を保持するために、2つの配列(LHS と RHS)を用意しています。三重のネストされたループを使い、左辺には ( a, b, c ) の全組み合わせの値を、右辺には ( d, e, f ) の全組み合わせの値を格納していきます。

その後、両方の配列をそれぞれソートし、共通する値を効率よく見つけられるようにしてから、findsamenumbers() 関数に渡します。

findsamenumbers() 関数では、2つの配列を先頭から順に比較しながら一致する値を探します。一致する要素が見つかった場合は、その値が両方の配列内で何回出現するか(出現頻度)を確認することで、すべての有効な組み合わせをもれなくカウントできるようにしています。

if(arr1[i] == arr2[j]){
    count++;
    int temp = arr1[i];
    while(temp==arr1[++i]){
        count++;
    }
    while(temp==arr2[++j]){
        count++;
    }

まとめ

この記事では、与えられた配列の要素を使って、6変数の方程式 ( a + b + c ) * e / d = f を満たす6つ組の個数を求める問題を解きました。左辺と右辺の全組み合わせを事前に生成し、ソート後に照合するというシンプルな手法により、効率よく答えを導き出せます。なお、このアプローチはC++だけでなく、C、Java、Python など他のプログラミング言語でも同様に実装することが可能です。

  1. C++で文字列の部分文字列の総数を求める方法を解説

    この記事では、与えられた文字列から作成できる空でない部分文字列の個数を求める方法について解説します。入力 : string = "moon" 出力 : 10 説明 : 部分文字列は m、o、o、n、mo、oo、on、moo、oon、moon の 10 個です。 入力 : string = "yellow" 出力 : 21解法のアプローチ文字列の長さを n とします。上の例からも分かるように、考えられるすべての部分文字列の個数を求めるには、長さ n、(n-1)、(n-2)、(n-3)、……2、1 の部分文字列の個数を順に加算していく必要があります。部分文

  2. C++で列車の停車駅の組み合わせ数を求める方法

    地点XとYの間にはn個の中間駅があるとします。ここで、「どの2つの停車駅も隣り合わない」という条件のもとで、s個の駅に停車する列車の配置方法が何通りあるかを求める問題を考えてみましょう。この記事では、停車駅の組み合わせ数を求めるためのアプローチを段階的に詳しく解説します。この問題は、本質的には組合せ論の問題であり、s個の停車駅の選び方の総数を求めることになります。 問題を解くアプローチ まず具体例として、中間駅が8個あり、そのうち3個の駅に停車させたい場合を考えてみます。 n = 8, s = 3 このとき、列車が停車できない駅は(n − s)、つまり5個残ることになります。 停車できない