Description
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天的心情值之和的期望值。
Data Constraint
30%:N≤20
50%:N≤2,000
100%:1≤M≤N≤1,000,000 1≤A,B,C≤1,000 1≤P,D<998244353
分析
很显然,我们应该先求概率。
设
fi
表示第i天是晴天的概率,
那么,
1−fi
就表示第i天是雨天的概率。
首先,可以从
fi−1
转移过来,
第i-1天的概率乘上这天不变天的概率,即
fi+=fi−1∗(1−p)
也可以从i-m-1天转移过来,
第i-m-1天变天了,之后的连续m天都是雨天,那么第i天就必定是晴天。
fi+=fi−m−1∗p
考虑每天的期望,
晴天的期望:
fi∗A
雨天的期望:
(1−fi)∗(d∗c+(1−d)∗b)
最后求和就可以了。
code
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#define N 1000003
#define mo 998244353
#define ll long long
using namespace std;
int n,m;
ll p,d,a,b,c,f[N],s,ans;
ll ksm(ll x,int y)
{
ll s=1;
while(y)
{
if(y%2)s=s*x%mo;
x=x*x%mo;
y>>=1;
}
return s;
}
int main()
{
freopen("daydream.in","r",stdin);
freopen("daydream.out","w",stdout);
scanf("%d%d%lld%lld%lld%lld%lld",&n,&m,&p,&d,&a,&b,&c);
f[0]=1;
s=(1+mo-d)*b%mo+c*d%mo;
s%=mo;
for(int i=1;i<=n;i++)
{
f[i]=f[i-1]*(mo+1-p)%mo;
if(i>=m)
{
f[i]=(f[i]+p*f[i-m-1])%mo;
}
ans=(ans+f[i]*a%mo+(mo+1-f[i])*s%mo)%mo;
}
printf("%lld",ans);
}