牛客寒假2-C算概率| 概率dp
思路
p[i] 表示第i题的正确率
1.假设已知前i-1题正确j道的概率是dp[i-1][j],考虑i题正确的概率
2.用dp[i][j]表示前i题正确j道的概率,推转移时,考虑前i-1题第j道题是否做对
容易想到前i题正确j道的概率 = (第i-1题中j-1题错误,且这题正确的概率) + (第i-1题中j题正确,且这题错误的概率)
即状态转移方程: dp[i][j] = dp[i-1][j-1]p[i] + dp[i-1][j](1-p[i])
考虑在取模下的递推: dp[i][j] = (dp[i-1][j-1]p[i]%mod + (dp[i-1][j](1-p[i]+mod)%mod )%mod;
3.边界问题:
容易想到 正确i题,正确0道的概率是 dp[i-1][0] * (1-p[i])
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 2010;
int n;
ll p[maxn];
ll dp[maxn][maxn];
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>p[i];
dp[0][0] = 1;
//初始化边界 前i题正确对0道的概率
for(int i=1;i<=n;i++){
dp[i][0] = dp[i-1][0] * ((1-p[i]) + mod) % mod;
}
// dp[i][j]表示前i题正确j道的概率
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
//递推关系: dp[i][j] = dp[i-1][j-1]*p[i] + dp[i-1][j]*(1-p[i])
dp[i][j] = (dp[i-1][j]*(1-p[i]+mod)%mod + dp[i-1][j-1]*p[i]%mod)%mod;
}
}
for(int i=0;i<=n;i++){
cout<<dp[n][i]<<" ";
}
return 0;
}