题目描述
牛牛刚刚考完了期末,尽管 牛牛 做答了所有
n
\text{}n
n 道题目,但他不知道有多少题是正确的。
不过,牛牛 知道第
i
\text{}i
i 道题的正确率是
p
i
p_i
pi 。
牛牛 想知道这
n
n
n 题里恰好有
0
,
1
,
…
,
n
0,1,\dots,n
0,1,…,n 题正确的概率分别是多少,对
1
0
9
+
7
10^9+7
109+7 取模。
对
1
0
9
+
7
10^9+7
109+7 取模的含义是:对于一个
b
≠
0
b\neq 0
b=0 的不可约分数 $a\over $,存在
q
\text{}q
q 使得
b
×
q
m
o
d
(
1
0
9
+
7
)
=
a
b\times q \bmod (10^9+7) =a
b×qmod(109+7)=a ,
q
\text{}q
q 即为
a
b
a\over b
ba 对
1
0
9
+
7
10^9+7
109+7 取模的结果。
输入描述:
第一行,一个正整数
n
\text{}n
n 。
第二行,
n
\text{}n
n 个整数
p
1
,
p
2
,
…
,
p
n
p_1,p_2,\dots,p_n
p1,p2,…,pn,在模
1
0
9
+
7
10^9+7
109+7 意义下给出。
保证
1
≤
n
≤
2000
1\leq n\leq 2000
1≤n≤2000。
输出描述:
输出一行 n + 1 \text{}n+1 n+1 个用空格隔开的整数表示答案(对 1 0 9 + 7 10^9+7 109+7 取模)。
输入
1
500000004
输出
500000004 500000004
说明
有 1 道题,做对的概率是 1 2 1 \over 2 21 ( 1 2 1 \over 2 21 在 模 1 0 9 + 7 意 义 下 为 500000004 在模 10^9+7 意义下为 500000004 在模109+7意义下为500000004 )。
题解
- 定义 d p [ i ] [ j ] 表 示 : 前 i 道 题 做 对 j 道 的 概 率 dp[i][j]表示:前i道题做对j道的概率 dp[i][j]表示:前i道题做对j道的概率
- 转移时考虑第j道题是否做对,转移方程为: d p [ i ] [ j ] = d p [ i − 1 ] [ j ] ∗ ( 1 − p i ) + f [ i − 1 ] [ j − 1 ] ∗ p i dp[i][j]=dp[i-1][j]*(1-p_i)+f[i-1][j-1]*p_i dp[i][j]=dp[i−1][j]∗(1−pi)+f[i−1][j−1]∗pi。
- 时间复杂度 O ( n 2 ) O(n^2) O(n2) 。
AC-Code
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2005 + 7;
const int mod = 1e9 + 7;
ll dp[maxn][maxn]; // 前i道题作对j道的概率
ll a[maxn];
int main() {
int n; cin >> n;
for (int i = 1; i <= n; ++i) cin >> a[i];
for (int i = dp[0][0] = 1; i <= n; ++i) {
dp[i][0] = dp[i - 1][0] * (mod + 1 - a[i]) % mod;
for (int j = 0; j <= n; ++j) {
dp[i][j] = (dp[i - 1][j] * (mod + 1 - a[i]) + dp[i - 1][j - 1] * a[i]) % mod;
}
}
for (int i = 0; i <= n; ++i)
cout << dp[n][i] << " ";
}