比赛地址:https://ac.nowcoder.com/acm/contest/3003
Accepted
- A - 做游戏
- B - 排数字
- C - 算概率
- D - 数三角
- E - 做计数
- F - 拿物品
- G - 判正误
- H - 施魔法
- I - 建通道
- J - 求函数
C - 算概率
解题思路:
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j] 表示前
i
i
i 道题作对
j
j
j 道的概率。
转移时考虑第
j
j
j 道题是否做对,状态转移方程:
d
p
[
i
]
[
j
]
=
d
p
[
i
−
1
]
[
j
]
∗
(
1
−
p
[
j
]
)
+
d
p
[
i
−
1
]
[
j
−
1
]
∗
p
[
j
]
dp[i][j]=dp[i-1][j]*(1-p[j])+dp[i-1][j-1]*p[j]
dp[i][j]=dp[i−1][j]∗(1−p[j])+dp[i−1][j−1]∗p[j] ,计算时取模。
Code:
#include <bits/stdc++.h>
#define IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2000 + 10;
int n;
ll p[N];
ll dp[N][N];//前i道题作对j道题的概率
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld", &p[i]);
}
dp[0][0] = 1;
for (int i = 1; i <= n; i++) {
//前i道题作对0道题
//p[i]是在模1e9+7意义下给出的,答案也是对1e9+7取模,就相当于平时的概率,直接用p[i]和(1 - p[i] + mod) % mod计算,计算时取模
dp[i][0] = dp[i - 1][0] * ((1 - p[i] + mod) % mod) % mod;
for (int j = 1; j <= i; j++) {
//dp[i-1][]是确定的了,所以dp[i][j]分第i道题做对、做错两种情况。
dp[i][j] = (dp[i - 1][j] * ((1 - p[i] + mod) % mod) % mod + dp[i - 1][j - 1] * p[i] % mod) % mod;
}
}
for (int i = 0; i <= n; i++) {
printf("%d%c", dp[n][i], i == n ? '\n' : ' ');
}
return 0;
}