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\)个人有\(j\)个活着的概率,\(f_{i,j}\)可以dp出来
\[f_{i,j} = f_{i - 1,j} \times d_i + f_{i - 1,j - 1} \times a_i\]
我们可以枚举每次\(g_{i,j}\)的i,然后skip掉,这样的复杂度是\(n^3\)的
然后就可以前缀后缀背包卷积NTT,或者单点删除的分治做法hhhhhhh
其实这个被背包删除物品可以做O(n)
逆着推一下就好了

代码


#include<cstdio>
#include<cstring>
#include<algorithm>
inline int read() {
    int x = 0,f = 1;
    char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c <= '9' && c >= '0') x = x * 10 + c - '0' ,c = getchar();
    return x * f;
}
const int mod = 998244353;
const int maxn = 2007;
long long b[maxn];
int n,m ;
long long p[maxn][maxn];
long long inv[maxn];
inline int add(int x,int y) {
    return x + y >= mod ? x + y - mod : x + y;
}
inline int fstpow(int x,int k) {
    int ret = 1;
    for(;k;k >>= 1,x = 1ll *x * x % mod)
        if(k & 1) ret = 1ll * ret * x % mod;
    return ret;
}
void solve1(int x,int P) {
    int rp = 1 + mod - P;
    for(int i = 0;i <= b[x];++ i) {
        if(i) p[x][i] = 1ll * p[x][i] * rp % mod;
        if(i < b[x]) p[x][i] = add(p[x][i] , 1ll * p[x][i + 1] * P % mod) ;
    }
}
int k;
void solve(int k) {
    static long long f[maxn],g[maxn],h[maxn],t[maxn];
    // f存活j个人的概率
    memset(f,0,sizeof f);
    f[0] = 1;
    for(int i = 1;i <= k;++ i) t[i] = read();
    for(int a,d,i = 1;i <= k;++ i) {
        a = 1 + mod - p[t[i]][0];
        d = p[t[i]][0];
        for(int j = i;j >= 0;-- j)
            f[j] = add((j ? 1ll * f[j - 1] * a % mod : 0) , 1ll * f[j] * d % mod);
    }
    for(int i = 1;i <= k;++ i) {
        h[i] = 0;
        int a = 1 + mod - p[t[i]][0];
        if(!p[t[i]][0])
            for(int j = 0;j < k;++ j) h[i] = add(h[i],1ll * f[j + 1] * inv[j + 1] % mod);
        else {
            int Inv = fstpow(p[t[i]][0],mod - 2);
            for(int j = 0;j < k;++ j) {
                g[j] = ((f[j] - (j ? 1ll * g[j - 1] * a % mod : 0) + mod) % mod) * Inv % mod;
                h[i] = add(h[i],1ll * g[j] * inv[j + 1] % mod);
            }
        }
        h[i] = 1ll * h[i] * a % mod;
    }
    for(int i = 1;i <= k;++ i) printf("%d ",h[i]);
    puts("");
}
main() {
    //freopen("facel5.in","r",stdin); freopen("w.out","w",stdout);
    n = read();
    for(int i = 1;i <= n;++ i) b[i] = read(), p[i][b[i]] = 1,inv[i] = fstpow(i,mod - 2);
    m = read();
    for(int op,i = 1;i <= m;i += 1) {
        op = read();
        if(!op) {
            int x = read(),u = read(),v = read();
            solve1(x,1ll * u * fstpow(v,mod - 2) % mod);
        }
        else
            solve(read());
    }   

    for(int i = 1;i <= n;++ i) {
        int sum = 0;
        for(int j = 1;j <= b[i];++ j)
            sum = add(sum , 1ll * j * p[i][j] % mod) ;
        printf("%d%c",sum,i != n ? ' ' : '\n');
    }
    return 0;
} 

原文地址:https://www.cnblogs.com/sssy/p/9581007.html

时间: 2024-11-05 18:48:07

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

#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]

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\)

loj#2076. 「JSOI2016」炸弹攻击 模拟退火

目录 题目链接 题解 代码 题目链接 loj#2076. 「JSOI2016」炸弹攻击 题解 模拟退火 退火时,由于答案比较小,但是温度比较高 所以在算exp时最好把相差的点数乘以一个常数让选取更差的的概率降低 代码 #include<ctime> #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #define gc getchar() #define

Loj #2541「PKUWC2018」猎人杀

Loj #2541. 「PKUWC2018」猎人杀 题目链接 好巧妙的题! 游戏过程中,概率的分母一直在变化,所以就非常的不可做. 所以我们将问题转化一下:我们可以重复选择相同的猎人,只不过在一个猎人被选择了过后我们就给他打上标记,再次选择他的时候就无效.这样与原问题是等价的. 证明: 设\(sum=\sum_iw_i,kill=\sum_{i被杀死了}w_i\). 攻击到未被杀死的猎人\(i\)的概率为\(P\). 则根据题意\(P=\frac{w_i}{sum-kill}\). 问题转化后:

Loj #2542. 「PKUWC2018」随机游走

Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次询问给定一个集合 \(S\),求如果从 \(x\) 出发一直随机游走,直到点集 \(S\) 中所有点都至少经过一次的话,期望游走几步. 特别地,点 \(x\)(即起点)视为一开始就被经过了一次. 答案对 $998244353 $ 取模. 输入格式 第一行三个正整数 \(n,Q,x\). 接下来 \(

Loj #2192. 「SHOI2014」概率充电器

Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完全由真随机数决定!SHOI 概率充电器,您生 活不可或缺的必需品!能充上电吗?现在就试试看吧!」 SHOI 概率充电器由 \(n-1\) 条导线连通了 \(n\) 个充电元件.进行充电时,每条导线是否可以导电以 概率决定,每一个充电元件自身是否直接进行充电也由概率决定.随后电能可以从直接充电的元件经

Loj #3111. 「SDOI2019」染色

Loj #3111. 「SDOI2019」染色 题目描述 给定 \(2 \times n\) 的格点图.其中一些结点有着已知的颜色,其余的结点还没有被染色.一个合法的染色方案不允许相邻结点有相同的染色. 现在一共有 \(c\) 种不同的颜色,依次记为 \(1\) 到 \(c\).请问有多少对未染色结点的合法染色方案? 输入格式 第一行有两个整数 \(n\) 和 \(c\),分别描述了格点图的大小和总的颜色个数. 之后两行,每行有 \(n\) 个整数:如果是 \(0\) 则表示对应结点未被染色,否

LOJ #2037. 「SHOI2015」脑洞治疗仪

#2037. 「SHOI2015」脑洞治疗仪 题目描述 曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见,我们将大脑视作一个 01 序列.1 代表这个位置的脑组织正常工作,0 代表这是一块脑洞. 1 0 1 0 0 0 1 1 1 0 脑洞治疗仪修补某一块脑洞的基本工作原理就是将另一块连续区域挖出,将其中正常工作的脑组织填补在这块脑洞中.(所以脑洞治疗仪是脑洞的治疗仪?) 例如,用上面第 8 号位置到第