题目链接

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;
}

最新文章

  1. Lua 栈的理解
  2. NPOI教程
  3. remount failed: Operation not permitted ,怎么办呢?
  4. SQL server 表之间的关系生成图
  5. Linux hrtimer分析(一)
  6. CSS3_边框属性之圆角的基本图形案例
  7. Android开发之显示通知
  8. while loading persisted sessions 异常解决方法
  9. JAVA HashMap详细介绍和示例
  10. [Angular 2] Using ng-model for two-way binding
  11. 如何在大型的并且有表分区的数据库中进行DBCC CHECKDB操作
  12. 【第四篇】Volley修改之GsonRequest
  13. &lt;pre&gt;标记的使用...
  14. 对于IE6版本图片透明。
  15. 基于javaMail的邮件发送--excel作为附件
  16. ONOS架构-系统组件
  17. POJ - 1850 Code(组合数学)
  18. how do I get the difference between two R named lists?
  19. 一起talk C栗子吧(第一百三十三回:C语言实例--创建进程时的内存细节)
  20. MySQL 数据库定时自动备份

热门文章

  1. I/O流、序列化
  2. 【Js】JSON对象、JSON字符的使用总结
  3. 宝塔漏洞 XSS窃取宝塔面板管理员漏洞 高危
  4. poj2230 欧拉回路
  5. SQL 公用表表达式(CTE)
  6. Xcode9新变化
  7. Migrating from MapReduce 1 (MRv1) to MapReduce 2 (MRv2, YARN)...
  8. Hibernate-ORM:13.Hibernate中的连接查询
  9. 【数据库】 SQL SERVER 2014 实用新特性
  10. hadoop中的方法的作用