牛客寒假算法集训营2--C[算概率](概率,递推)

题意:
在这里插入图片描述思路:
1.当时首先在分数取模那里卡了一下,以为要求逆元,但是其实给的概率就是在取模意义下,要的结果也是在取模意义下的概率,所以其实直接用取模意义下的概率进行概率的求解即可。
2.这道题在不考虑时间复杂度的情况下要求出x道题正确的概率很简单,普通的概率乘法公式即可。但是每次都去枚举哪些题正确哪些题错误的话时间复杂度达到了O(n^3)。故要考虑怎么“记忆”当前状态前面已经枚举过的状态,故采用递推的方式。
设f(i,j)表示前 i 道题做对 j 道的概率(此处概率均指取模意义下)。
设p[i]为第 i 题正确的概率,q[i]为第 i 道题错误的概率。
则有状态转移方程:f(i,j)=f(i-1,j) q[i] + f(i-1,j-1) p[i],注意j==0时没有右式的第二项。起点f(0,0)为取模意义下的1。
这样时间复杂度变为O(n^2)

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=2020;

ll p[maxn];//p[i]表示第i道题做对的概率; 
ll q[maxn];//q[i]表示第i道题做错的概率;

ll f[maxn][maxn];//f[i][j]表示前i道题做对j道的mod意义下的概率; 
//状态转移方程为f[i][j]=(f[i-1][j]*q[i]%mod+f[i-1][j-1]*p[i]%mod)%mod;  

int main()
{
	int i,j;
	int n;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		scanf("%lld",&p[i]);
		q[i]=(1-p[i]+mod)%mod;
	}
	memset(f,false,sizeof(f));
	f[0][0]=mod+1;
	for(i=1;i<=n;i++)
	{
		for(j=0;j<=i;j++)
		{
			if(j!=0) f[i][j]=(f[i-1][j]*q[i]%mod+f[i-1][j-1]*p[i]%mod)%mod;
			else f[i][j]=f[i-1][j]*q[i]%mod;
		}
	}
	for(i=0;i<=n;i++)
	{
		if(i!=n)
		{
			printf("%lld ",f[n][i]);
		}
		else
		{
			printf("%lld\n",f[n][i]);
		}
	}
	return 0;
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值