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
",ans);
}
原文地址:https://www.cnblogs.com/Extended-Ash/p/7887160.html