牛客寒假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;
}
posted @ 2020-02-16 14:32  fishers  阅读(158)  评论(0编辑  收藏  举报