Điểm:
500
Thời gian:
4.0s
Bộ nhớ:
256M
Input:
bàn phím
Output:
màn hình
Cho \(N\) là một số nguyên dương lẻ.
Có \(N\) đồng xu, được đánh số \(1,2,3,\cdots,N\). Với mỗi \(i(1 \leq i \leq N)\), khi đồng xu \(i\) được gieo, xác suất nó xảy ra mặt ngửa là \(p_i\) và xác suất nó xảy ra mặt úp là \(1−p_i\).
Kaninho gieo \(N\) đồng xu cùng một lúc. Tính xác suất để ta thu được số lượng đồng xu ngửa lớn hơn số lượng đồng xu úp.
Input
- Dòng thứ nhất chứa số nguyên dương lẻ \(N(1 \leq N \leq 2999)\)
- Dòng thứ hai chứa \(n\) số thực có 2 chữ số ở hàng thập phân \(p_i(0<p_i<1)\)
Output
- In ra đáp án cần tìm. (Gọi \(x\) là đáp án của bạn, \(y\) là đáp án của bài toán, thì \(x\) được chấp nhận là đúng nếu \(|x−y|<10^{−9}\))
Example
Test 1
Input
3
0.30 0.60 0.80
Output
0.612
Note
Xác suất của mỗi trường hợp có số lượng đồng xu ngửa lớn hơn số lượng đồng xu úp là :
\(P(ngua,ngua,ngua)\)=\(0.3∗0.6∗0.8=0.144\)
\(P(up,ngua,ngua)\)=\(0.7∗0.6∗0.8=0.336\)
\(P(ngua,up,ngua)\)=\(0.3∗0.4∗0.8=0.096\)
\(P(ngua,ngua,up)\)=\(0.3∗0.6∗0.2=0.036\)
Như vậy, xác suất có số lượng mặt ngửa lớn hơn số lượng đồng xu úp là: \(0.144+0.336+0.096+0.036=0.612\)
Bình luận
Hint
Bài này thực ra có 3 cách để quy hoạch động
Cách 1
Gọi \(dp[i][j]\) là xác suất khi tung \(i\) đồng xu đầu tiên được \(j\) đồng xu ngửa.
Trường hợp 1: Đồng xu \(i\) là đồng ngửa => Ta cần tính xác suất để tung \(i-1\) đồng đầu tiên được \(j-1\) đồng ngửa. Vậy xác suất cho trường hợp này là \(dp[i-1][j-1]*p[i]\).
Trường hợp 2: Đồng xu \(i\) là đồng sấp => Ta cần tính xác suất để tung \(i-1\) đồng đầu tiên được \(j\) đồng ngửa. Vậy xác suất cho trường hợp này là \(dp[i-1][j]*(1-p[i])\).
Vậy xác suất để tung \(i\) đồng được \(j\) đồng ngửa là \(dp[i-1][j-1]*p[i]+dp[i-1][j]*(1-p[i])\)
Xác suất để tung \(n\) đồng được số đồng ngửa nhiều hơn số đồng sấp là \(dp[n][n/2+1]+dp[n][n/2+2]+...+dp[n][n]\)
AC code
Cách 2 ##
(Hơi phức tạp hơn tý)
Gọi \(dp[i][j]\) là xác suất khi tung \(i\) đồng xu đầu tiên được số đồng xu ngửa nhiều hơn số đồng xu sấp \(j\) đồng (\(j\) có thể âm).
Trường hợp 1: Đồng xu \(i\) là đồng ngửa => Ta cần tính xác suất để tung \(i-1\) đồng đầu tiên được số đồng ngửa nhều hơn số đồng sấp là \(j-1\) đồng. Vậy xác suất cho trường hợp này là \(dp[i-1][j-1]*p[i]\).
Trường hợp 2: Đồng xu \(i\) là đồng sấp => Ta cần tính xác suất để tung \(i-1\) đồng đầu tiên được số đồng ngửa nhiều hơn số đồng sấp là \(j+1\) đồng. Vậy xác suất cho trường hợp này là \(dp[i-1][j+1]*(1-p[i])\).
Vậy xác suất để tung \(i\) đồng được \(j\) đồng ngửa là \(dp[i-1][j-1]*p[i]+dp[i-1][j+1]*(1-p[i])\)
Xác suất để tung \(n\) đồng được số đồng ngửa nhiều hơn số đồng sấp là \(dp[n][1]+dp[n][2]+...+dp[n][n]\)
AC code
Cách 3
(Khó code nhất nhưng dễ hiểu nhất)
Gọi \(dp[i][j]\) là xác suất khi tung \(i+j\) đồng xu đầu tiên được \(i\) đồng xu ngửa và \(j\) đồng xu sấp.
Trường hợp 1: Đồng xu \(i+j\) là đồng ngửa => Ta cần tính xác suất để tung \(i+j-1\) đồng đầu tiên được \(i-1\) đồng ngửa và \(j\) đồng sấp. Vậy xác suất cho trường hợp này là \(dp[i-1][j]*p[i]\).
Trường hợp 2: Đồng xu \(i+j\) là đồng sấp => Ta cần tính xác suất để tung \(i+j-1\) đồng đầu tiên được \(i\) đồng ngửa và \(j-1\) đồng sấp. Vậy xác suất cho trường hợp này là \(dp[i][j-1]*(1-p[i])\).
Vậy xác suất để tung \(i\) đồng được \(j\) đồng ngửa là \(dp[i-1][j]*p[i]+dp[i][j-1]*(1-p[i])\)
Xác suất để tung \(n\) đồng được số đồng ngửa nhiều hơn số đồng sấp là \(dp[n/2+1][n/2]+dp[n/2+2][n/2-1]+...+dp[n][0]\)
AC code
Ghi chú: Ta dùng lệnh cout.precision(9) để lấy đến 9 chữ số sau dấu thập phân.
Độ phức tạp của 3 cách này đều là \(O(N^2)\)
5 bình luận nữa