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

C++で2個のサイコロをN回投げたときに指定した合計が出る確率を求める方法

この記事では、「合計値」と「サイコロを投げる回数」が入力として与えられたときに、2個のサイコロをN回投げた結果、指定した合計が出る確率を求める方法をC++で解説します。

確率とは、与えられたデータの集合の中から望む結果を得られる可能性のことを指します。確率の範囲は0から1の間であり、0は「不可能」を、1は「確実」を表します。

具体例

入力:sum = 12, N = 1
出力:確率 = 1/36
説明:2個のサイコロを1回投げたときの出目の組み合わせは
(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 1), (2, 2), (2, 3), (2, 4),
(2, 5), (2, 6), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6), (4, 1), (4, 2),
(4, 3), (4, 4), (4, 5), (4, 6), (5, 1), (5, 2), (5, 3), (5, 4), (5, 5), (5, 6),
(6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (6, 6) の全36通りです。
この中で合計が12になるのは (6, 6) の1通りだけなので、確率は 1/36 となります。

入力:sum = 4, N = 6
出力:確率は 1/2985984

プログラムで使用するアプローチ

  • 合計値と、サイコロを投げる回数Nを入力として受け取ります
  • 2個のサイコロをN回投げたときに目的の合計が出る確率を求めるには、次の公式を使います:(有利な場合の数 ÷ 全体の場合の数) ^ N
  • まず、2個のサイコロを1回投げたときにその合計が出る確率を計算します(例:1/9など)
  • N回投げたときの確率は、以下のようにして求めます
  • Probability2 = (Probability1) ^ N = Probability1 のN乗

なお、全体の場合の数は6×6=36通りあり、各合計値に対する有利な場合の数は二重ループで全組み合わせを調べることで求められます。最終的な分母が大きくなりすぎないよう、最大公約数(GCD)を使って分数を約分してからN乗を計算するのがポイントです。

アルゴリズム

開始
ステップ1 → 確率を計算する関数を宣言する
    int probability(int sum, int times)
    float res = 0.0 と total = 36.0 を宣言・初期化する
    long int probab = 0 を宣言・初期化する
    ループ For i = 1 ~ i <= 6、i++
        ループ For j = 1 ~ j <= 6、j++
            IF ((i + j) == sum)
                res をインクリメントする
            End
        End
    End
    int gcd1 = __gcd((int)res, (int)total) を宣言・設定する
    res = res / (float)gcd1 を設定する
    total = total / (float)gcd1 を設定する
    probab = pow(total, times) を設定する
    probab を返す
ステップ2 → main() 内で
    int sum = 4、times = 6 を宣言・設定する
    probability(sum, times) を呼び出す
終了

C++での実装例

#include <bits/stdc++.h>
using namespace std;
// 2個のサイコロをN回投げたときに合計が出る確率を計算する関数
int probability(int sum, int times) {
    float res = 0.0, total = 36.0;
    long int probab = 0;
    // 全36通りの組み合わせから、合計が一致する場合の数を数える
    for (int i = 1; i <= 6; i++) {
        for (int j = 1; j <= 6; j++) {
            if ((i + j) == sum)
            res++;
        }
    }
    // 最大公約数で約分する
    int gcd1 = __gcd((int)res, (int)total);
    res = res / (float)gcd1;
    total = total / (float)gcd1;
    // 分母のN乗を計算する
    probab = pow(total, times);
    return probab;
}
int main() {
    int sum = 4, times = 6;
    cout<<"probability is : ";
    cout << "1" << "/" << probability(sum, times);
    return 0;
}

出力結果

probability is : 1/2985984

この実装では、sum = 4 となる組み合わせが (1,3)、(2,2)、(3,1) の3通り存在し、36と3の最大公約数である3で約分すると確率は 1/12 となります。これを6回繰り返すため、12^6 = 2985984 となり、最終的な確率は 1/2985984 と求められます。

  1. C++で配列のすべての部分集合の合計値を効率的に求める方法

    n個の要素を持つ配列Aが与えられたとき、その配列のすべての部分集合の合計値の総和を求める問題を考えてみましょう。例えば、配列が A = [5, 6, 8] の場合、各部分集合とその合計は以下のようになります。部分集合合計5566885, 6116, 8145, 8135, 6, 819総和76考え方のポイントn個の要素を持つ配列の場合、部分集合の数は(空集合を含めて)2n 個存在します。ここで重要な性質に注目してみましょう。各要素は、ちょうど 2(n−1) 回だけ部分集合に出現するという点です。この性質を利用すると、すべての部分集合の合計値の総和は次の式で一発に計算できます。総和 = (配列の

  2. C++の配列パズル:減算演算子を使わずに「自分以外の要素の合計」を求める方法

    今回は、配列に関する興味深い問題を紹介します。n個の要素を持つ配列が与えられ、それをもとに同じくn個の要素を持つ別の配列を作成します。ただし、新しい配列のi番目には、元の配列のi番目の要素を除いたすべての要素の合計を格納します。さらに重要な制約として、減算演算子(-)を使用してはいけないという条件が課されています。 問題のポイント もし減算が使えるのであれば、話は簡単です。まず全要素の合計を求めておき、そこからi番目の要素を引いた値を新しい配列のi番目に格納すればよいだけです。しかし、この問題では減算が禁止されているため、別のアプローチが必要になります。 そこで、各位置i(0〜n-1)について