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天的心情值之和的期望值。
Input
一行7个整数N,M,P,D,A,B,C,如题目所描述(其中给出的P,D是模998244353意义下的值)
Output
一个整数,为答案。
Sample Input
Sample Input1
3 1 499122177 499122177 1 2 3
Sample Input2
233 23 372752072 54252411 10 20 22
Sample Output
Sample Output1
311951365
Sample Output2
651727164
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
Hint
样例一输出的值对应的实数是4.6875
Solution
解决这道题如果直接计算总期望值的话,将会有些困难。
于是我们转而先计算概率。设 F[i] 表示 第 i 天是晴天的概率。
考虑第
i−1 天的天气,如果是晴天,那么则有:F[i]+=F[i−1]∗(1−P)。-
如果是台风天,说明第 i−1 天是连续台风天的第 m 天,则第
i−m−1 天必然是上一个晴天。则有:
F[i]+=F[i−m−1]∗P初始化是: F[0]=1 (第 0 天必定是晴天),于是就可以 O(N) 求出概率了。
接着计算总期望,讨论第 i 天的情况:
①:是晴天,则期望为:
F[i]∗A ;②:是台风天,则期望为: (1−F[i])∗(C∗D+B∗(1−D)) (杀人案件的期望);
那么把这 N 天的①②两种期望全部相加即为答案,时间复杂度为 O(N) 。
注意:所给的概率都是模意义下的,设给定的模数为 Mo ,处理时都应模 Mo 。
若给的概率在模意义下为 x ,则概率
1−x 就等于 Mo+1−x ,证明略。
Code
#include<cstdio>
using namespace std;
const int mo=998244353;
int n,m;
long long p,d,a,b,c,ans;
long long f[1000001];
int main()
{
scanf("%d%d%lld%lld%lld%lld%lld",&n,&m,&p,&d,&a,&b,&c);
long long k=(c*d%mo+(mo+1-d)*b%mo)%mo;
for(int i=f[0]=1,l=mo+1-p;i<=n;i++)
{
f[i]=f[i-1]*l%mo;
if(i-m-1>=0) f[i]=(f[i]+f[i-m-1]*p)%mo;
ans=(ans+f[i]*a)%mo;
ans=(ans+(mo+1-f[i])*k)%mo;
}
printf("%lld",ans);
return 0;
}