题目链接

BZOJ5340

题解

我们能很容易维护每个人当前各种血量的概率
设\(p[u][i]\)表示\(u\)号人血量为\(i\)的概率
每次攻击的时候,讨论一下击中不击中即可转移
是\(O(Qm^2)\)的

现在考虑一下结界
如果我们设\(f[u][i]\)表示除了\(u\)还存活\(i\)个人的概率
那么
\[ans[u] = (1 - p[u][0]) \sum\limits_{i = 0}^{k - 1} \frac{f[u][i]}{i + 1}\]
所以我们只需计算\(f[u][i]\)
\(f[u][i]\)同样可以通过枚举剩余每个人存活与否进行转移,是\(O(n^3)\)的,复杂度过高
我们考虑计算\(g[i]\)表示剩余\(i\)人的概率
枚举\(u\)
\[g'[i] = g[i]p[u][0] + g[i - 1](1 - p[u][0])\]
即可\(O(n^2)\)计算\(g[i]\)
如果我们拿\(f[u][i]\)来计算\(g[i]\)的话
\[g[i] = f[u][i]p[u][0] + f[u][i - 1](1 - p[u][0])\]
那么
\[f[u][i] = \frac{g[i] - f[u][i - 1](1 - p[u][0])}{p[u][0]}\]
也可以\(O(n^2)\)递推

这样我们就做完了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 205,maxm = 105,INF = 1000000000,P = 998244353;
inline int read(){int out = 0,flag = 1; char c = getchar();while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}return out * flag;
}
LL p[maxn][maxm],f[maxn][maxn],g[maxn][maxn],n,m[maxn],id[maxn];
LL INV[maxn];
inline LL qpow(LL a,LL b){LL ans = 1;for (; b; b >>= 1,a = 1ll * a * a % P)if (b & 1) ans = 1ll * ans * a % P;return ans;
}
inline LL inv(int x){if (x <= n) return INV[x];return qpow(x,P - 2);
}
int main(){n = read();REP(i,n) m[i] = read(),p[i][m[i]] = 1;INV[0] = 1; INV[1] = 1;for (int i = 2; i <= n; i++) INV[i] = 1ll * (P - P / i) * INV[P % i] % P;LL Q = read(),opt,u,v,pp,x,k;while (Q--){opt = read();if (!opt){x = read(); u = read(); v = read(); pp = u * inv(v) % P;p[x][0] = (p[x][0] + pp * p[x][1] % P) % P;for (int i = 1; i <= m[x]; i++)p[x][i] = ((p[x][i] * (1 - pp) % P + p[x][i + 1] * pp % P) % P + P) % P;}else {k = read();cls(g); g[0][0] = 1;for (int i = 1; i <= k; i++){u = id[i] = read();g[i][0] = g[i - 1][0] * p[u][0] % P;for (int j = 1; j <= i; j++){g[i][j] = ((g[i - 1][j] * p[u][0] % P + g[i - 1][j - 1] * (1 - p[u][0]) % P) % P + P) % P;}}for (int i = 1; i <= k; i++){u = id[i];LL ans = 0,Inv = inv(p[u][0]);if (!p[u][0]){for (int j = 0; j < k; j++)f[u][j] = g[k][j + 1];}else {f[u][0] = 1ll * g[k][0] * Inv % P;for (int j = 1; j < k; j++){f[u][j] = (1ll * (g[k][j] - 1ll * f[u][j - 1] * (1 - p[u][0]) % P) % P * Inv % P + P) % P;}}for (int j = 0; j < k; j++){ans = (ans + 1ll * f[u][j] * inv(j + 1) % P) % P;}ans = (1ll * ans * (1ll - p[u][0]) % P + P) % P;printf("%lld",ans);if (i < k) putchar(' ');else puts("");}}}for (int i = 1; i <= n; i++){LL ans = 0;for (int j = 1; j <= m[i]; j++)ans = (ans + 1ll * j * p[i][j] % P) % P;printf("%lld",ans);if (i < n) putchar(' ');else puts("");}return 0;
}

转载于:https://www.cnblogs.com/Mychael/p/9070652.html

BZOJ5340 [Ctsc2018]假面 【概率dp】相关推荐

  1. P4564 [CTSC2018]假面(期望)

    P4564 [CTSC2018]假面 首先容易看出结界技能对第二问敌方剩余生命值期望没有影响. 如何求出第iii个人的剩余生命值期望? 只需要根据Ei=∑j=0aij×fi,jE_i=\sum_{j= ...

  2. 2018.09.01 poj3071Football(概率dp+二进制找规律)

    传送门 概率dp简单题. 设f[i][j]表示前i轮j获胜的概率. 如果j,k能够刚好在第i轮相遇,找规律可以发现j,k满足: (j−1)>>(i−1)(j−1)>>(i−1) ...

  3. Discovering Gold LightOJ - 1030[概率dp或者记忆化搜索]

    题目大意:有一个[1,n][1,n][1,n]的数轴,数轴上的每个对应位置上都有金矿,你初始位置是1,然后你每次都会投色子决定你下一步跳到哪里,如果你跳出了nnn,那么你就要重新投.问你跳到nnn的时 ...

  4. 【原创】概率DP总结 by kuangbin

    概率DP主要用于求解期望.概率等题目. 转移方程有时候比较灵活. 一般求概率是正推,求期望是逆推.通过题目可以体会到这点. 首先先推荐几篇参考的论文: <信息学竞赛中概率问题求解初探> & ...

  5. poj 3071 Football(概率dp)

    http://poj.org/problem? id=3071 大致题意:有2^n个足球队分成n组打比赛.给出一个矩阵a[][],a[i][j]表示i队赢得j队的概率.n次比赛的流程像这样France ...

  6. HDU 5001 概率DP || 记忆化搜索

    2014 ACM/ICPC Asia Regional Anshan Online 给N个点,M条边组成的图,每一步能够从一个点走到相邻任一点,概率同样,问D步后没走到过每一个点的概率 概率DP  測 ...

  7. hdu 3853 LOOPS 概率DP

    简单的概率DP入门题 代码如下: 1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 ...

  8. HDU - 4035 Maze(概率dp)

    题目链接:点击查看 题目大意:给出一个 n 个点的树,初始时位于点 1 ,每个点都会给出一个概率 k[ i ] 和一个概率 e[ i ] ,其代表的意义分别是: k[ i ] :在点 i 有 k[ i ...

  9. SDUT - 2623 The number of steps(概率dp)

    题目链接:点击查看 题目大意:给出一个 n 层的三角形,第一层有 1 个点,第二层有 2 个点,第三层有 3 个点 ... 第 n 层有 n 个点,现在规定从第一层的点向下出发: 如果左下方有点并且右 ...

最新文章

  1. 保姆级NLP学习路线来啦!
  2. 13.3Runtime 类中的主要方法
  3. [云炬创业基础笔记]第六章商业模式测试6
  4. AtCoder Beginner Contest 230
  5. php下载 微信头像图片_php保存微信用户头像到本地或者服务器的完美方案!
  6. 第四部分 Calendar使用示例
  7. signature=0d9b3a8f96c5f64e92cd85aaf7e70ac0,Scale controller
  8. php面向对象之策略模式,php策略模式的学习--引自《深入php面向对象模式与实践》...
  9. java类中各成员初始化的顺序
  10. Flutter之ScrollView简析
  11. Oracle 11g简体中文版的安装过程及图解
  12. 计算机实验室场地报告,实验室申请报告.doc
  13. 前端特效 - 前置- - 01. 百叶窗
  14. 谷歌浏览器弹出Chrome版本太旧解决方式
  15. WIN10添加策略组
  16. pychart绘制中国地图用英文省名
  17. matplotlib plot显示marker超出边界部分
  18. 最新《PHP全套学习课程》
  19. 心脏滴血漏洞简单攻击
  20. java配置环境变量path(JAVA配置环境变量失败)

热门文章

  1. 最新版,别的可以不用看了,zabbix 监控 esxi
  2. 老话题,不要在遍历容器中增删容器数据
  3. Mysql修复损坏表并写脚本自动修复
  4. 删除隐藏的旧网卡信息的解决办法
  5. 流水账之都市:我是一个客居者
  6. pyqt webview 执行js
  7. 注意力机制的本质中文版代码
  8. 高可用、可扩展、稳定和安全的消息队列ActiveMQ特点分析
  9. 理解Kubernetes(2): 应用的各种访问方式
  10. windows server 更改默认服务端口