質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

解決済

1回答

1501閲覧

サイコロにおける確率問題

grape_ll

総合スコア83

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

0クリップ

投稿2020/05/17 08:17

問題

問題

疑問があるコード

Java

1import java.util.Scanner; 2public class Main{ 3 public static void main(String[] args){ 4 Scanner sc = new Scanner(System.in); 5 int n=sc.nextInt(); 6 long d = sc.nextLong(); 7 int[] p={2,3,5}; 8 int[] co=new int[3]; 9 for(int i=0; i<3; i++){ 10 while(d%p[i]==0){ 11 co[i]++; //2の数、3の数、4の数を数えている 12 d/=p[i]; //2,3,4で割っている 13 } 14 } 15 if(d>1){  16 System.out.println(0); //7以上の素数があると確率は0 17 return; 18 } 19 double[][][][] dp=new double[n+1][co[0]+1][co[1]+1][co[2]+1];  //[ふる数+1][2の数+1][3の数+1][5の数+1] 20 dp[0][0][0][0]=1; //最初は確率1 21 for(int i=0; i<n; i++){                        22 for(int j=0; j<=co[0]; j++){ 23 for(int k=0; k<=co[1]; k++){ 24 for(int t=0; t<=co[2]; t++){ 25 dp[i+1][Math.min(j+1,co[0])][k][t]+=dp[i][j][k][t]*(1.0/6.0); 26 dp[i+1][j][Math.min(co[1],k+1)][t]+=dp[i][j][k][t]*(1.0/6.0); 27 dp[i+1][j][k][Math.min(co[2],t+1)]+=dp[i][j][k][t]*(1.0/6.0); 28 dp[i+1][j][k][t]+=dp[i][j][k][t]*(1.0/6.0); 29 dp[i+1][Math.min(co[0],j+2)][k][t]+=dp[i][j][k][t]*(1.0/6.0); 30 dp[i+1][Math.min(co[0],j+1)][Math.min(co[1],k+1)][t]+=dp[i][j][k][t]*(1.0/6.0); 31 } 32 } 33 } 34 } 35 System.out.println(dp[n][co[0]][co[1]][co[2]]); 36 } 37} 38

質問内容

上記のコードで以下の部分は何をしているのかが分からないので教えていただきたいです。
右側にコメントしてあるのは私がこういうことではないかと考えたものなので間違えているところがあれば教えていただけると幸いです。

Java

1 for(int i=0; i<n; i++){                        2 for(int j=0; j<=co[0]; j++){ 3 for(int k=0; k<=co[1]; k++){ 4 for(int t=0; t<=co[2]; t++){ 5 dp[i+1][Math.min(j+1,co[0])][k][t]+=dp[i][j][k][t]*(1.0/6.0); 6 dp[i+1][j][Math.min(co[1],k+1)][t]+=dp[i][j][k][t]*(1.0/6.0); 7 dp[i+1][j][k][Math.min(co[2],t+1)]+=dp[i][j][k][t]*(1.0/6.0); 8 dp[i+1][j][k][t]+=dp[i][j][k][t]*(1.0/6.0); 9 dp[i+1][Math.min(co[0],j+2)][k][t]+=dp[i][j][k][t]*(1.0/6.0); 10 dp[i+1][Math.min(co[0],j+1)][Math.min(co[1],k+1)][t]+=dp[i][j][k][t]*(1.0/6.0); 11 } 12 } 13 } 14 }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

dpのインデックスのうち1つ目が「さいころを振った個数」2つ目~4つ目が「さいころの目の積に含まれる素因数2,3,5の個数」に当たります。配列の値はその状況になる確率を表します。
例えば「さいころ3つ振って3,4,5が出る」確率は、3,4,5の積には素因数2が2つ、3が1つ、5が1つ含まれるので、dp[3][2][1][1]に含まれます。
ここで、さいころ4つ振った場合のそれぞれの確率、例えばdp[4][2][1][1]を考えると、さいころ3個の状態からさいころを追加で1個振ることを考えて、

  • 3回目までの各素因数の個数が2,1,1の状態で1が出る
  • 3回目までの各素因数の個数が1,1,1の状態で2が出る
  • 3回目までの各素因数の個数が2,0,1の状態で3が出る
  • 3回目までの各素因数の個数が0,1,1の状態で4が出る
  • 3回目までの各素因数の個数が2,1,0の状態で5が出る
  • 3回目までの各素因数の個数が2,0,0の状態で6が出る

のいずれかであり、これらは排反(いずれも同時に起こらない)ので、それぞれの3回目時点の確率×1/6の和を取ればいいのです。
つまり、このコードは

java

1dp[i+1][Math.min(j+1,co[0])][k][t]+=dp[i][j][k][t]*(1.0/6.0); //2が出る 2dp[i+1][j][Math.min(co[1],k+1)][t]+=dp[i][j][k][t]*(1.0/6.0); //3が出る 3dp[i+1][j][k][Math.min(co[2],t+1)]+=dp[i][j][k][t]*(1.0/6.0); //5が出る 4dp[i+1][j][k][t]+=dp[i][j][k][t]*(1.0/6.0); //1が出る 5dp[i+1][Math.min(co[0],j+2)][k][t]+=dp[i][j][k][t]*(1.0/6.0); //4が出る 6dp[i+1][Math.min(co[0],j+1)][Math.min(co[1],k+1)][t]+=dp[i][j][k][t]*(1.0/6.0); //6が出る

という確率を加えていっています。

投稿2020/05/17 08:36

swordone

総合スコア20669

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

grape_ll

2020/05/18 11:17

具体例、ありがとうございます!しっかり理解することが出来ました! また機会があればよろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問