题目

有\(n\)个敌方单位,初始生命值分别为\(m_1,\cdots,m_n\) ;

假面可以释放\(Q\)个技能:

$op = 0 \ , \ id , u , v $ 表示对\(id\)号敌人有\(\frac{u}{v}\)的概率造成\(1\)点伤害;

$op = 1 \ , \ k \ , \ a_1,\cdots a_k $  表示在这些位置中生命值为正的位置里随机选择一个位置释放结界;

你需要对每个\(op=1\),输出\(a_1,\cdots, \ a_k\)中结界的期望(\(op=1\)操作最多\(C\)次);

$n \le 200 \ , \ Q \le 200000 \ , \ C \le 1000 ,m_i \le 100 $ ;

题解

  • Part 1

  • 设\(f_{i,j}\)表示\(i\)受到的伤害为\(j\)的概率,设\(x=\frac{u}{v}\),则\(f_{i,j} = x \times f_{i,j-1} + (1-x) \times f_{i,j}\)

  • \(p_i\)表示\(i\)号敌人存活的概率,$p_i \ = \ \sum_{j=0}^{m_i-1} f_{i,j} $

  • 剩余生命的期望\(q_i = \sum_{j=0}^{m_i-1}f_{i,j} \times (m_i-j)\)

  • **Part 2 **

  • 把所有\(a_i\)拎出来讨论,设存活概率为\(p_i\) , \(g_{i,j}\)表示不算第\(i\)个敌人,存活的个数为\(j\)的概率,\(G_j\)表示所有人都算上存活个数为\(j\)的概率,一个人对于\(G\)的贡献是:

    $G_{j} = p_i \times G_{j-1} \ + \ (1-p_i) \times G_{j} $

  • 这个式子是可逆的,即:

    \[\begin{cases}
    g_{i,j} &= \frac{G_j - p_i \times g_{i,j-1}}{1-p_i} & p_i != 1 \\
    g_{i,j} &= G_{j+1} & p_i==1
    \end{cases}
    \]

  • 时间复杂度:\(O(QM\ + \ nMC)\)

    #include<bits/stdc++.h>
    #define vec vector<int>
    #define pb push_back
    #define mod 998244353
    #define ll long long
    using namespace std;
    const int N=810;
    int n,m,a[N],b[N],f[N][N],tot,ny[N],p[N],g[N],t[N];
    char gc(){
    static char*p1,*p2,s[1000000];
    if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
    return(p1==p2)?EOF:*p1++;
    }
    int rd(){
    int x=0;char c=gc();
    while(c<'0'||c>'9')c=gc();
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc();
    return x;
    }
    int pw(int x,int y){
    int re=1;
    if(y<0)y+=mod-1;
    while(y){
    if(y&1)re=(ll)re*x%mod;
    y>>=1;x=(ll)x*x%mod;
    }
    return re;
    }
    void inc(int&x,int y){x+=y;if(x>=mod)x-=mod;}
    void solve(){
    for(int i=1;i<=tot;++i)g[i]=0;g[0]=1;
    for(int i=1;i<=tot;++i){
    int x=b[i],y=(mod+1-x)%mod;
    for(int j=tot;~j;--j){
    g[j]=(ll)g[j]*y%mod;
    if(j)inc(g[j],(ll)g[j-1]*x%mod);
    }
    }
    for(int j=0;j<=tot;++j)t[j]=g[j];
    for(int i=1;i<=tot;++i){
    int re=0,x=b[i],y=pw((mod+1-x)%mod,mod-2);
    if(x==1){for(int j=0;j<tot;++j)g[j]=g[j+1];g[tot]=0;}
    else{
    g[0]=(ll)g[0]*y%mod;
    for(int j=1;j<=tot;++j)g[j]=(g[j]-(ll)g[j-1]*x%mod+mod)%mod*y%mod;
    }
    for(int j=0;j<=tot;++j){
    inc(re,(ll)ny[j+1]*b[i]%mod*g[j]%mod);
    g[j]=t[j];
    }
    printf("%d ",re);
    }
    puts("");
    }
    int main(){
    // freopen("faceless.in","r",stdin);
    // freopen("faceless.out","w",stdout);
    n=rd();
    for(int i=1;i<=n;++i)a[i]=rd(),f[i][0]=p[i]=1;
    ny[1]=1;for(int i=2;i<=n<<2;++i)ny[i]=1ll*(mod-mod/i)*ny[mod%i]%mod;
    m=rd();
    for(int i=1;i<=m;++i){
    int op,id,x,y;
    op=rd();
    if(!op){
    id=rd();x=rd();y=rd();
    x=(ll)x*pw(y,mod-2)%mod;
    y=(mod+1-x)%mod;p[id]=0;
    for(int j=a[id]-1;~j;--j){
    f[id][j]=(ll)f[id][j]*y%mod;
    if(j)inc(f[id][j],(ll)f[id][j-1]*x%mod);
    inc(p[id],f[id][j]);
    }
    }else {
    tot=rd();
    for(int j=1;j<=tot;++j)b[j]=p[rd()];
    solve();
    }
    }
    for(int i=1;i<=n;++i){
    int x=0;
    for(int j=0;j<a[i];++j)inc(x,(ll)(a[i]-j)*f[i][j]%mod);
    printf("%d ",x);
    }
    return 0;
    }

【loj2552】【CTSC2018】假面的更多相关文章

  1. BZOJ5340: [Ctsc2018]假面

    BZOJ5340: [Ctsc2018]假面 https://lydsy.com/JudgeOnline/problem.php?id=5340 分析: 背包,只需要求\(g_{i,j}\)表示强制活 ...

  2. BZOJ5340 & 洛谷4564 & LOJ2552:[CTSC2018]假面——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5340 https://www.luogu.org/problemnew/show/P4564 ht ...

  3. 并不对劲的bzoj5340:loj2552:uoj399:p4564: [Ctsc2018]假面

    题目大意 有\(n\)(\(n\leq200\))个非负整数\(m_1,m_2,...,m_n\)(\(\forall i\in[1,n],m_i\leq100\)),有\(q\)(\(q\leq2* ...

  4. [CTSC2018] 假面 | 期望 DP

    题目链接 LOJ 2552 Luogu P4564 考场上这道题我先是写了个70分暴力,然后发现似乎可以NTT,然鹅问题是--我没学过NTT,遂脑补之,脑补出来了,下午出成绩一看,卡成暴力分(70)- ...

  5. BZOJ5340: [Ctsc2018]假面【概率+期望】【思维】

    LINK 思路 首先考虑减血,直接一个dp做过去,这个部分分不难拿 然后是\(op=1\)的部分 首先因为要知道每个人被打的概率,所以需要算出这个人活着的时候有多少个人活着时概率是什么 那么用\(g_ ...

  6. [CTSC2018]假面

    题目 先来考虑一下第一问,血量有\(P\)的概率减\(1\) 由于我们最后需要求每一个人的期望血量,于是考虑维护出每个人处于不同血量时候的概率 一个简单\(dp\)即可 \[dp_{i,j}=dp_{ ...

  7. bzoj 5340: [Ctsc2018]假面

    Description 题面 Solution 生命值范围比较小,首先维护每一个人在每个血量的概率,从而算出生存的概率,设为 \(a[i]\) 询问时,只需要考虑生存的人数,可以 \(DP\) 设 \ ...

  8. BZOJ5340 [Ctsc2018]假面 【概率dp】

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

  9. [CTSC2018]假面(概率DP)

    考场上以为CTSC的概率期望题都不可做,连暴力都没写直接爆零. 结果出来发现全场70以上,大部分AC,少于70的好像极少,感觉血亏. 设a[i][j]表示到当前为止第i个人的血量为j的概率(注意特判血 ...

  10. UOJ399 CTSC2018 假面 期望、DP

    传送门 \(Q \leq 200000 , C \leq 1000 , m_i \leq 100\)-- 先考虑如何维护最后一次操作时所有人的血量期望.不难发现我们需要的复杂度是\(O(Qm_i)\) ...

随机推荐

  1. ZooKeeper学习笔记(二)——内部原理

    zookeeper学习笔记(二)--内部原理 1. zookeeper的节点的类型 总的来说可以分为持久型和短暂型,主要区别如下: 持久:客户端与服务器端断开连接的以后,创建的节点不会被删除: 持久化 ...

  2. 1、C#多线程基础理论

    系统为应用程序分配所需的内存以及其他资源,内存和资源的物理分离叫做进程.   进程是以线程为单位竞争CPU,那么什么是线程呢? 线程可看成一个可执行的指令单元,他使用进程中的数据,包含若干条指令,进程 ...

  3. C#使用Autofac实现控制反转IoC和面向切面编程AOP

    Autofac是一个.net下非常优秀,性能非常好的IOC容器(.net下效率最高的容器),加上AOP简直是如虎添翼.Autofac的AOP是通过Castle(也是一个容器)项目的核心部分实现的,名为 ...

  4. C#采集摄像头实时画面和抓拍

    在.net中,并没有简单直接的操纵摄像头的类.那么如何简单快捷地采集摄像头的画面,进行抓拍等操作呢?答案是调用SharpCapture!专业采集摄像头画面等数据的类库.下面开始演示关键代码,您也可以在 ...

  5. spring boot 分布式锁组件 spring-boot-klock-starter

    基于redis的分布式锁spring-boot starter组件,使得项目拥有分布式锁能力变得异常简单,支持spring boot,和spirng mvc等spring相关项目 快速开始 sprin ...

  6. this关键字。

    一.this关键字主要有三个应用: (1)this调用本类中的属性,也就是类中的成员变量: (2)this调用本类中的其他方法: (3)this调用本类中的其他构造方法,调用时要放在构造方法的首行. ...

  7. div中的“内容”水平垂直居中

    1. div高度自适应的情况 div在不设置高度的时候,会被里面的内容撑开,内容自动填充在div中,无论是一行内容还是多行内容,此时不需要设置垂直居中,内容自动在中间的, 想要看的更直观些,只需要加上 ...

  8. springboot+druid+mybatis

    pom.xml <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId> ...

  9. jQuery知识梳理20190818

    目录 jQuery知识梳理20190818 1. 时间绑定和解绑 2. 区别mouseover与mouseenter 3. 时间委托(委派/代理) 4 . 多库共存 5.window.onload与$ ...

  10. tar.bz2解压异常

    问题描述: [root@mvp-dd ~]# tar jxf ffmpeg-.tar.bz2 tar (child): bzip2: Cannot exec: No such file or dire ...