Jzoj5244 Daydreamin
温馨提示:本文附带bgm
worldwideD最近有午睡的习惯~
某日中午,他做了一个梦:梦见有一个怪人,她去一个岛上住N+1天(编号为0到N)。这是在大洋中的岛,每天要么是晴天,要么刮台风。
她到达岛的第0天是晴天(这样她才能上岸)。然后对于第i天,假如是晴天,那么有P(0≤P≤1)的几率会变天:接下来连续M天都刮台风,然后第i+M+1天必然会转晴。
天气对她的心情会有影响,用一个值来描述她每一天的心情:如果第i天是晴天,那么这个值为A;如果是雨天,那么岛上有D(0≤D≤1)的几率会发生杀人案件,如果没发生杀人案件,这个值为B,否则为C。
worldwideD醒来了,他想知道编号1到N天的心情值之和的期望值。
这是一道期望dp的好题
因为每一天对答案的贡献都是独立的而且线性可加
所以我们设f[i]表示第i天为晴天的概率,考虑以下转移
如果第i−1天为晴天,那么就有1−p的概率第i天也是晴天,f[i−1]×(1−p)转移到f[i]
如果第i−1天是雨天,那么第i−m−1天肯定是晴天,所以f[i−m−1]×p转移到f[i]
求出了f就可以得到Ans=∑f[i]∗a+(1−f[i])∗(b∗(1−d)+c∗d)
#pragma GCC optimize("O3") #pragma G++ optimize("O3") #include<stdio.h> #include<string.h> #include #define L long long #define M 998244353 using namespace std; L n,m,a,b,c,p,d; L f[1000010],ans=0; int main(){ freopen("daydream.in","r",stdin); freopen("daydream.out","w",stdout); scanf("%lld%lld%lld%lld%lld%lld%lld",&n,&m,&p,&d,&a,&b,&c); f[0]=1; for(int i=1;i<=n;++i){ f[i]=f[i-1]*(M+1-p)%M; if(i>m) f[i]=(f[i]+f[i-m-1]*p%M)%M; } for(int i=1;i<=n;++i) ans=(ans+(f[i]*a%M+(M+1ll-f[i])*(b*(M+1-d)%M+c*d%M)%M))%M; printf("%lld\n",ans); }