package main import ( "bufio" "fmt" "os" "strconv" ) var s = bufio.NewScanner(os.Stdin) func next() string { // s.Split(bufio.ScanWords) // 削除: Scan後に呼ぶとPanicになるため s.Scan() return s.Text() } func nextInt() int { i, e := strconv.Atoi(next()) if e != nil { panic(e) } return i } func nextLong() int64 { i, e := strconv.ParseInt(next(), 10, 64) if e != nil { panic(e) } return i } func nextIntArray() []int { // ScanLinesの使用はPanicの原因となるため、nextIntを3回呼ぶ形式に変更 // recv関数内でP[0]〜P[2]を使用しているため、3要素と仮定 data := make([]int, 3) for i := 0; i < 3; i++ { data[i] = nextInt() } return data } /*  あと N年で歯が連続でK本残っている場合のK本残る期待値 */ func recv(N int, K int, P []int) float64 { if N == 0 || K == 0 { return float64(K) } if memo[N][K] != -1 { return memo[N][K] } if K == 1 { memo[N][K] = ((100.0 - float64(P[0])) / 100.0) * recv(N-1, K, P) } else { memo[N][K] = 0 // ビットシフトの右オペランドはunsignedである必要があるためキャスト for mask := 0; mask < (1 << uint(K)); mask++ { prob := 1.0 for i := 0; i < K; i++ { //左端と右端の確率 bad := 0.0 if i == 0 || i == K-1 { //連続という前提なので 1 や K-2のは歯もある bad = float64(P[1]) / 100.0 } else { bad = float64(P[2]) / 100.0 } //歯が残る if (mask & (1 << uint(i))) > 0 { prob *= 1 - bad } else { prob *= bad } } left := 0 if prob == 0.0 { continue } for i := 0; i < K; i++ { if (mask & (1 << uint(i))) == 0 { //歯の連続が途切れた時の確率 memo[N][K] += prob * recv(N-1, left, P) left = 0 } else { //歯が残っている left++ } } memo[N][K] += prob * recv(N-1, left, P) } } return memo[N][K] } func fill(arr []float64, v float64) { for i := 0; i < len(arr); i++ { arr[i] = v } } var memo [][]float64 func main() { // Scan開始前にSplitを設定しないとPanicになるため、ここに移動 s.Split(bufio.ScanWords) A := nextInt() //P[0] 両方の歯がないときの虫歯になる確率 //P[1] 片方の歯がないときの虫歯になる確率 //P[0] 両方の歯があるときの虫歯になる確率 memo = make([][]float64, 80*20) P := nextIntArray() for i := 0; i < 80; i++ { memo[i] = make([]float64, 20) fill(memo[i], -1) } // fmt.Println(memo) fmt.Println(2 * recv(80-A, 14, P)) }