#2552. 「CTSC2018」假面

2552. 「CTSC2018」假面



一道“普及难度”DP题。。。然而考场上没想出来。

一堆人题解里说“只要会期望和逆元都能AC”,我ssfd

还是在看完题解之后照着题解打的

大概就是设$f[i][j]$表示第$i$个人血量为$j$的概率

然而1号操作的转移就是$f[i][j]\leftarrow f[i][j](1-p)+f[i][j+1]p$。

二号操作就比较麻烦了。

可以枚举每个人,设$g[i]$为存活$i$个人的概率(不包括枚举的人),那么转移就是$g[i]\leftarrow g[i]dead[x]+g[i-1]alive[x]$

这个人被选的概率为$alive[x]*\sum_{i=0}^{k-1}\frac{g[i]}{i+1}$

其中$alive[x]$是$x$存活的概率,$dead[x]$是$x$死亡的概率

显然$dead[x]=f[x][0],alive[x]=1-f[x][0]$

那么得到一个二号操作一次$O(n^3)$的优秀算法。

得到70分的好成绩。

然后想想优化

好像每两次产生的$g$只会有两处不同(删一个人再加一个人可以得到新的$g$)

那么可以先不枚举,直接算出总的$g$数组

再每次删一个

$g‘[i]=g[i]dead[x]+g[i-1]alive[x]$

化成

$g[i]=\frac{g‘[i]-g[i-1]*alive[x]}{dead[x]}$

然后就可以$O(n)$求出每次的$g$数组辣

完结撒花

我还是太菜了。

#include<bits/stdc++.h>
#define il inline
#define vd void
#define mod 998244353
typedef long long ll;
il int gi(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
il vd exgcd(ll a,ll b,ll&x,ll&y){
    if(b==0)x=1,y=0;
    else{
        exgcd(b,a%b,y,x);
        y-=a/b*x;
    }
}
std::map<int,int>M;
il ll inv(ll a){
    if(M.find(a)!=M.end())return M[a];
    ll A=a,B=mod;
    ll x,y;
    exgcd(A,B,x,y);
    x=(x%mod+mod)%mod;
    M[a]=x;
    return x;
}
ll f[201][102];
ll alive[201],dead[201];
ll g[201],gg[201],a[201],m[201];
int main(){
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
    freopen("output.out","w",stdout);
#endif
    int n=gi();
    for(int i=1;i<=n;++i)f[i][m[i]=gi()]=1;
    int Q=gi(),op,id,u,v;
    for(int i=1;i<=Q;++i){
        op=gi();
        if(op==0){
            id=gi(),u=gi(),v=gi();
            int p=1ll*u*inv(v)%mod;
            f[id][0]=(f[id][0]+1ll*f[id][1]*p%mod)%mod;
            for(int j=1;j<=m[id];++j)f[id][j]=(f[id][j]*(mod+1-p)%mod+f[id][j+1]*p%mod)%mod;
        }else{
            for(int j=1;j<=n;++j)alive[j]=(mod+1-f[j][0])%mod;
            for(int j=1;j<=n;++j)dead[j]=f[j][0];
            int tot=gi();
            for(int j=1;j<=tot;++j)a[j]=gi();
            for(int j=1;j<=n;++j)g[j]=0;
            g[0]=1;
            for(int j=1;j<=tot;++j){
                for(int k=j;k;--k)g[k]=(g[k-1]*alive[a[j]]+g[k]*dead[a[j]]%mod)%mod;
                g[0]=g[0]*dead[a[j]]%mod;
            }
            for(int x=1;x<=tot;++x){
                if(dead[a[x]]==0)for(int j=0;j<tot;++j)gg[j]=g[j+1];
                else{
                    gg[0]=1;
                    for(int j=1;j<=tot;++j)if(x!=j)gg[0]=gg[0]*dead[a[j]]%mod;
                    for(int j=1;j<tot;++j)gg[j]=(g[j]-gg[j-1]*alive[a[x]]%mod+mod)%mod*inv(dead[a[x]])%mod;
                }
                ll ans=0;
                for(int k=1;k<=tot;++k)ans+=gg[k-1]*inv(k)%mod;
                printf("%lld ",alive[a[x]]*(ans%mod)%mod);
            }
            puts("");
        }
    }
    for(int i=1;i<=n;++i){
        int ans=0;
        for(int j=1;j<=m[i];++j)ans=(ans+j*f[i][j]%mod)%mod;
        printf("%d ",ans);
    }
    puts("");
    return 0;
}

原文地址:https://www.cnblogs.com/ssfdJR/p/9042981.html

时间: 2024-10-07 15:12:04

#2552. 「CTSC2018」假面的相关文章

loj#2552. 「CTSC2018」假面

题目链接 loj#2552. 「CTSC2018」假面 题解 本题严谨的证明了我菜的本质 对于砍人的操作好做找龙哥就好了,blood很少,每次暴力维护一下 对于操作1 设\(a_i\)为第i个人存活的概率,\(d_i\)为死掉的概率,\(g_{i,j}\)是除i以外活了j个人的概率 那个选中i人的答案就是 \[a_i\times\sum_{j = 0} ^{k - 1}\frac{g_{i,j}}{j + 1}\] 对于\(g_{i,j}\) ,设\(f_{i,j}\)表示前\(i\)个人有\(

Loj #2553. 「CTSC2018」暴力写挂

Loj #2553. 「CTSC2018」暴力写挂 题目描述 temporaryDO 是一个很菜的 OIer .在 4 月,他在省队选拔赛的考场上见到了<林克卡特树>一题,其中 \(k = 0\) 的部分分是求树 \(T\) 上的最长链.可怜的 temporaryDO 并不会做这道题,他在考场上抓猫耳挠猫腮都想不出一点思路. 这时,善良的板板出现在了空中,他的身上发出璀璨却柔和的光芒,荡漾在考场上.''题目并不难.'' 板板说.那充满磁性的声音,让 temporaryDO 全身充满了力量. 他

Loj #2554. 「CTSC2018」青蕈领主

Loj #2554. 「CTSC2018」青蕈领主 题目描述 "也许,我的生命也已经如同风中残烛了吧."小绿如是说. 小绿同学因为微积分这门课,对"连续"这一概念产生了浓厚的兴趣.小绿打算把连续的概念放到由整数构成的序列上,他定义一个长度为 \(m\) 的整数序列是连续的,当且仅当这个序列中的最大值与最小值的差,不超过\(m-1\).例如 \(\{1,3,2\}\) 是连续的,而 \(\{1,3\}\) 不是连续的. 某天,小绿的顶头上司板老大,给了小绿 \(T\)

AC日记——「HNOI2017」单旋 LiBreOJ 2018

#2018. 「HNOI2017」单旋 思路: set+线段树: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #define maxtree maxn<<2 int val[maxtree],tag[maxtree],L[maxtree],R[maxtree],mid[maxtree]; int op[maxn],ki[maxn],bi[maxn],cnt,size,n,ch[maxn]

「随笔」基于当下的思考

马德,说好的技术blog,变成日记本了... 下午的时候莫名其妙的感到很颓废,因为自己的不够强大感到忧虑和危机感十足.现在每每行走在技术的道路上,常觉得如履薄冰,如芒在背. 上大学之前和现在的心态其实差别挺大的,视野的开阔远远不止局限于自己的脚下.不过,这里的「上大学之前」只是一个时间描述词,并不觉得大学是最适合学习的地方,我很失望. 世界上的人无论性别,区域,宗教,兴趣爱好,总可以在互联网上找到志趣相同的人,总是可以不断打破自己的常识与惯性思维.总是有在相同领域比自己更强的人,挺好的. 关于知

「Unity」与iOS、Android平台的整合:3、导出的Android-Studio工程

本文属于「Unity与iOS.Android平台的整合」系列文章之一,转载请注明出处. Unity默认导出的是Android-Eclipse工程,毕竟Eclipse for Android开发在近一两年才开始没落,用户量还是非常巨大的. 个人认为AndroidStudio非常好用,能轻易解决很多Eclipse解决不了或者很难解决的问题. 所以我将Unity导出的Andoid工程分为Eclipse和AndroidStudio两部分. 不过我之后的相关内容都会使用AndroidStudio,希望依然

大数据和「数据挖掘」是何关系?---来自知乎

知乎用户,互联网 244 人赞同 在我读数据挖掘方向研究生的时候:如果要描述数据量非常大,我们用Massive Data(海量数据)如果要描述数据非常多样,我们用Heterogeneous Data(异构数据)如果要描述数据既多样,又量大,我们用Massive Heterogeneous Data(海量异构数据)--如果要申请基金忽悠一笔钱,我们用Big Data(大数据) 编辑于 2014-02-2817 条评论感谢 收藏没有帮助举报作者保留权利 刘知远,NLPer 4 人赞同 我觉得 大数据

开放的智力8:实用「成功学」

可实现的「成功学」 现在我想为这里的年轻人介绍一种可实现的「成功学」.希望这个我自创的理论,可以改变很多人的一生. 当我们评价一个事情值不值得去做.应该花多少精力去做的时候,应该抛弃单一的视角,而是分两个不同的维度来看,一是该事件将给我带来的收益大小(认知.情感.物质.身体方面的收益皆可计入),即「收益值」:二是该收益随时间衰减的速度,我称为「收益半衰期」,半衰期长的事件,对我们的影响会持续得较久较长. 这两个维度正交以后就形成了一个四象限图.我们生活.学习和工作中的所有事情都可以放进这个图里面

Linux 小知识翻译 - 「syslog」

这次聊聊「syslog」. 上次聊了「日志」(lgo).这次说起syslog,一看到log(日志)就明白是怎么回事了.syslog是获取系统日志的工具. 很多UINIX系的OS都采用了这个程序,它承担了「获取系统全部的日志」这个维持系统正常运行的重要任务. syslog的本体是「syslogd」这个daemon(一般翻译成守护进程),常驻内存中获取日志. syslog的特点是可以通过配置文件「/etc/syslog.conf」,对「哪种应用程序?哪种重要度的信息?记录在哪个文件中?」等进行细致的