流星雨(概率dp)

链接:https://ac.nowcoder.com/acm/contest/368/C
来源:牛客网
 

题目描述

现在一共有n天,第i天如果有流星雨的话,会有wi颗流星雨。

第i天有流星雨的概率是pi。

如果第一天有流星雨了,那么第二天有流星雨的可能性是p2+P,否则是p2。相应的,如果第i−1 (i≥2)天有流星雨,第i天有流星雨的可能性是pi+P,否则是pi。

求n天后,流星雨颗数的期望。

输入描述:

 

第一行三个整数,n,a,b,其中n为天数,P=a/b

第二行n个整数wiwi。

接下来n行,每行两个整数,x,y,第i+2行表示第i天有流星雨的概率pi=xypi=xy。

1≤n≤105, 1≤a,b,x,y,wi≤109, pi+P≤1.0

输出描述:

 

一行一个整数,为答案对109+7109+7 取模的结果。

即设答案化为最简分式后的形式为abab,其中a和b互质。输出整数 x 使得bx≡a(mod 109+7)且0≤x<109+7。可以证明这样的整数x是唯一的。

 

 

1、概率可以用逆元去解决处理,无需自己写一个函数处理分数的相加相减,p1是下雨,逆元中(1-p1+mod)%mod也是代表不下雨;

2、该题期望有两种算法:总概率p*总数量num;也可以当前i下雨的概率pi*num[i],然后求和。

有了以上知识就可以轻松写出代码了,由于自己菜,不懂这些,当时就是不会写,现在懂了~

​
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
const ll mod=1e9+7;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); 
for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll num[maxn];
ll d[maxn][2];
int main()
{
	int n;
	ll a,b;
	cin>>n>>a>>b;
	ll p=a*powmod(b,mod-2)%mod;
	for(int i=1;i<=n;i++) scanf("%lld",&num[i]);
	ll ans=0;
	for(int i=1;i<=n;i++)
	{
		scanf("%lld%lld",&a,&b);
		if(i==1)
		{
			ll p1=a*powmod(b,mod-2)%mod;
			d[1][1]=p1;
			d[1][0]=(1-p1+mod)%mod;
			ans=p1*num[1]%mod;
			continue;
		}
		ll p1=a*powmod(b,mod-2)%mod;//下 
		ll p0=(1-p1+mod)%mod;
		ll p2=(p1+p)%mod;//下 
		ll p3=(1-p2+mod)%mod;
		d[i][0]=(d[i-1][0]*p0%mod+d[i-1][1]*p3%mod)%mod;
		d[i][1]=(d[i-1][0]*p1%mod)+(d[i-1][1]*p2%mod)%mod;
		ans=(ans+d[i][1]*num[i]%mod)%mod;
	}
	cout<<ans<<endl;
}

​

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长沙大学ccsu_deer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值