超简单(super)

题目描述

有一个n面的骰子,第i面的数是vi,朝上的概率是pi。

教室的最后一排有一个人,不停地抛这个骰子,直到某一面朝上了两次,就停止抛骰子,但他不知道所有朝上的面的数字的和的期望E是多少。

老班一脸嘲讽:“这不是超简单嘛。”

输入

输入的第一行包含一个正整数n。

输入的第二行包含n个正整数,表示vi。

输入的第三行包含n个非负整数,表示模998244353意义下的pi,保证所有pi的和为1。

n,vi,pi的含义见问题描述。

输出

输出一行一个非负整数E表示模998244353意义下的E。

样例输入

<span style="color:#333333"><span style="color:#333333">【样例输入】
2
1 2
332748118 665496236
</span></span>

样例输出

<span style="color:#333333"><span style="color:#333333">【样例输出】
961272344
</span></span>

提示

【样例说明】

骰子共有2个面。

第一面的数为1,朝上的概率为1/3;

第二面的数为2,朝上的概率为2/3。

所有情况列举如下:

第1次朝上的面

第2次朝上的面

第3次朝上的面

朝上的面的和

概率

1

1

/

2

1/9

1

2

1

4

2/27

1

2

2

5

4/27

2

1

1

4

2/27

2

1

2

5

4/27

2

2

/

4

4/9

所以E=2*1/9+4*2/27+5*4/27+4*2/27+5*4/27+4*4/9=110/27。

【子任务】

测试点

n

vi,pi

1~4

≤8

<998244353

5~8

≤50

9~12

≤100

13~20

≤500

noip2017模拟-wmd


solution

期望dp

令f[i][j]表示前i张牌选j张得期望

若f[i][j]=PS,新加入i点,那么新的期望为P*pi*(S+vi)

展开得到PS*pi+P*pi*vi

于是我们还需维护期望的和g[i][j]=P转移式有了 

f[i][j]=f[i-1][j]+f[i-1][j-1]*pi+g[i-1][j-1]*vi

我们可以枚举哪一位为出现两次的

效率O(n^3)

jyc神犇有优化

因为这个dp与数的顺序无关(不同顺序丢进去出来的是一个结果)

我们可以把最后一维当成我要禁掉的

倒推出n-1维

效率O(n^2)

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 505
#define ll long long
#define mod 998244353
using namespace std;
int n;
ll v[maxn],p[maxn],f[maxn][maxn],g[maxn][maxn],ans,h[maxn];
int main(){
cin>>n;
for(int i=1;i<=n;i++)scanf("%lld",&v[i]);
for(int i=1;i<=n;i++)scanf("%lld",&p[i]);
h[0]=1;
for(int i=1;i<=n;i++)h[i]=(h[i-1]*i)%mod;
for(int i=0;i<=n;i++)g[i][0]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++){
f[i][j]=f[i-1][j]+(f[i-1][j-1]*p[i])%mod+((g[i-1][j-1]*p[i])%mod*v[i])%mod;
f[i][j]%=mod;
g[i][j]=g[i-1][j]%mod+g[i-1][j-1]*p[i]%mod;
}
for(int b=1;b<=n;b++){
int vb=v[b],pb=p[b];
for(int j=1;j<=n;j++){
f[n-1][j]=f[n][j]-(f[n-1][j-1]*pb)%mod-((g[n-1][j-1]*pb)%mod*vb)%mod;
f[n][j]%=mod;
g[n-1][j]=g[n][j]-g[n-1][j-1]*pb%mod;
}
n--;
for(int i=0;i<=n;i++){
ll tmp=(f[n][i]*pb)%mod*pb;tmp%=mod;
tmp=tmp+g[n][i]*pb%mod*pb%mod*2*vb%mod;
ans=ans+(tmp*h[i+1])%mod;ans%=mod;
}
n++;
}
ans=(ans%mod+mod)%mod;
cout<<ans<<endl;
return 0;
}

最新文章

  1. 使用excel快速制表 拒绝粗心
  2. cp 命令(转)
  3. yii-mail yii 发送邮件
  4. 通过代码设置radiobutton不同方位图标的两种方法
  5. asp.net mvc,做 301 永久重定向
  6. ACM字符串处理算法经典:字符串搜索
  7. HDU 1198 Farm Irrigation (并检查集合 和 dfs两种实现)
  8. Qt之打包发布(NSIS详解)
  9. Apache2 三种MPM对比分析
  10. Linux下connect超时处理【总结】
  11. linux系统管理--进程管理
  12. Java EE中的容器和注入分析,历史与未来
  13. Python001-操作MSSQL(Microsoft sql server)基础示例(一)
  14. Linux常用的工具软件安装
  15. 【模板】cdq分治代替树状数组(单点修改,区间查询)
  16. composer安装laravel框架时未生成Vendor解决办法
  17. linux tmux 工具使用 tmux.conf 文件
  18. subversion与TortoiseSVN的使用
  19. Stanford机器学习笔记-9. 聚类(K-means算法)
  20. Heroku免费版限制

热门文章

  1. python_30_购物车复习
  2. python_28_dictionary补充
  3. cuda api查询问题
  4. CUDA实现数组倒序
  5. c#树形结构
  6. macbook pro开机键盘键盘和触摸板没反应问题
  7. centos7中使用LVM管理磁盘和挂载磁盘
  8. 懒人的mysql管理脚本
  9. Python知识点进阶——生成器
  10. STM32位带操作