結果

問題 No.162 8020運動
コンテスト
ユーザー yuki2006
提出日時 2015-03-05 22:15:16
言語 Go
(1.25.5)
結果
AC  
実行時間 124 ms / 5,000 ms
コード長 2,570 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 12,816 ms
コンパイル使用メモリ 245,312 KB
実行使用メモリ 7,848 KB
最終ジャッジ日時 2026-01-01 17:37:07
合計ジャッジ時間 15,667 ms
ジャッジサーバーID
(参考情報)
judge5 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 26
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

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))

}
0