分析

首先容易得出这样一个事实,在若干物品中最先被选出的是编号为\(i\)的物品的概率为\(\frac{W_i}{\sum_{j=1}^{cnt}W_j}\)。

假设树是一棵外向树,即父亲比儿子先选(一个点比它的子树中的所有其他的点先选),我们可以令\(f(i,j)\)表示以\(i\)为根的子树,子树内的总权值为\(j\),子树内的选取顺序合法的概率,转移类似树上分组背包。

那么我们现在需要考虑如何处理儿子比父亲先选的情况,其实可以直接容斥,减去父亲比儿子先选的概率就好了,注意这样的子树不要统计到\(f(i,j)\)的第二维中。

代码

#include <bits/stdc++.h>

#define rin(i,a,b) for(int i=(a);i<=(b);++i)
#define irin(i,a,b) for(int i=(a);i>=(b);--i)
#define trav(i,a) for(int i=head[a];i;i=e[i].nxt)
#define Size(a) (int) a.size()
#define pb push_back
#define mkpr std::make_pair
#define fi first
#define se second
#define lowbit(a) ((a)&(-(a)))
typedef long long LL; using std::cerr;
using std::endl; inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*f;
} const int MAXN=1005;
const int MOD=998244353; int n,ecnt,head[MAXN];
int p[MAXN][4],siz[MAXN];
int f[MAXN][MAXN*3],g[MAXN*3];
int inv[MAXN*3]; struct Edge{
int to,nxt;
}e[MAXN<<1]; inline void add_edge(int bg,int ed){
++ecnt;
e[ecnt].to=ed;
e[ecnt].nxt=head[bg];
head[bg]=ecnt;
} inline int qpow(int x,int y){
int ret=1,tt=x%MOD;
while(y){
if(y&1)ret=1ll*ret*tt%MOD;
tt=1ll*tt*tt%MOD;
y>>=1;
}
return ret;
} void dfs(int x,int pre){
f[x][0]=1;
trav(i,x){
int ver=e[i].to;
if(ver==pre)continue;
dfs(ver,x);
memset(g,0,sizeof g);
if(i&1){
irin(j,siz[x]*3,0)rin(k,1,siz[ver]*3)
g[j+k]=(g[j+k]+1ll*f[x][j]*f[ver][k])%MOD;
}
else{
int sum=0;
rin(j,1,siz[ver]*3)sum=(sum+f[ver][j])%MOD;
irin(j,siz[x]*3,0){
g[j]=(g[j]+1ll*f[x][j]*sum)%MOD;
rin(k,1,siz[ver]*3)g[j+k]=(g[j+k]-1ll*f[x][j]*f[ver][k]%MOD+MOD)%MOD;
}
}
memcpy(f[x],g,sizeof g);
siz[x]+=siz[ver];
}
memset(g,0,sizeof g);
rin(i,0,siz[x]*3)rin(j,1,3)
g[i+j]=(g[i+j]+1ll*f[x][i]*p[x][j]%MOD*j%MOD*inv[i+j])%MOD;
memcpy(f[x],g,sizeof g);
++siz[x];
} void init(int n){
inv[1]=1;
rin(i,2,n)inv[i]=(-1ll*(MOD/i)*inv[MOD%i]%MOD+MOD)%MOD;
} int main(){
n=read();init(n*3);
rin(i,1,n){
int sum=0;
rin(j,1,3)sum+=p[i][j]=read();
int invsum=qpow(sum,MOD-2);
rin(j,1,3)p[i][j]=1ll*p[i][j]*invsum%MOD;
}
rin(i,2,n){
int u=read(),v=read();
add_edge(u,v);
add_edge(v,u);
}
dfs(1,0);
int ans=0;
rin(i,1,n*3)ans=(ans+f[1][i])%MOD;
printf("%d\n",ans);
return 0;
}

[LOJ3124][CTS2019|CTSC2019]氪金手游:树形DP+概率DP+容斥原理的更多相关文章

  1. 「CTS2019」氪金手游

    「CTS2019」氪金手游 解题思路 考场上想出了外向树的做法,居然没意识到反向边可以容斥,其实外向树会做的话这个题差不多就做完了. 令 \(dp[u][i]\) 表示单独考虑 \(u\) 节点所在子 ...

  2. 【CTS2019】氪金手游(动态规划)

    [CTS2019]氪金手游(动态规划) 题面 LOJ 洛谷 题解 首先不难发现整个图构成的结构是一棵树,如果这个东西是一个外向树的话,那么我们在意的只有这棵子树内的顺序关系,子树外的关系与这棵子树之间 ...

  3. [LibreOJ 3124]【CTS2019】氪金手游【容斥原理】【概率】【树形DP】

    Description Solution 首先它的限制关系是一个树形图 首先考虑如果它是一个外向树该怎么做. 这是很简单的,我们相当于每个子树的根都是子树中最早出现的点,概率是容易计算的. 设DP状态 ...

  4. Loj #3124. 「CTS2019 | CTSC2019」氪金手游

    Loj #3124. 「CTS2019 | CTSC2019」氪金手游 题目描述 小刘同学是一个喜欢氪金手游的男孩子. 他最近迷上了一个新游戏,游戏的内容就是不断地抽卡.现在已知: - 卡池里总共有 ...

  5. 「CTS2019 | CTSC2019」氪金手游 解题报告

    「CTS2019 | CTSC2019」氪金手游 降 智 好 题 ... 考场上签到失败了,没想容斥就只打了20分暴力... 考虑一个事情,你抽中一个度为0的点,相当于把这个点删掉了(当然你也只能抽中 ...

  6. [CTS2019]氪金手游

    [CTS2019]氪金手游 各种情况加在一起 先考虑弱化版:外向树,wi确定 i合法的概率就是wi/sw sw表示子树的w的和,和子树外情况无关 这些概率乘起来就是最终合法的概率 如果都是外向树, f ...

  7. SGU 495 Kids and Prizes:期望dp / 概率dp / 推公式

    题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=495 题意: 有n个礼物盒,m个人. 最开始每个礼物盒中都有一个礼物. m个人依次随 ...

  8. LOJ3124 CTS2019 氪金手游 概率、容斥、树形DP

    传送门 D2T3签到题可真是IQ Decrease,概率独立没想到然后就20pts滚粗了 注意题目是先对于所有点rand一个权值\(w\)然后再抽卡. 先考虑给出的关系是一棵外向树的情况.那么我们要求 ...

  9. LOJ 3124 「CTS2019 | CTSC2019」氪金手游——概率+树形DP

    题目:https://loj.ac/problem/3124 看了题解:https://www.cnblogs.com/Itst/p/10883880.html 先考虑外向树. 考虑分母是 \( \s ...

随机推荐

  1. CF450A 【Jzzhu and Children】

    普通的模拟题这题用一个队列容器来模拟队列元素是pair类型的,first用来存每个小朋友想要的糖数,second用来存小朋友的序号,然后开始模拟,模拟出口是当队列迟到等于1时就输出当前队列里小朋友的序 ...

  2. 【计算机网络】-介质访问控制子层-无线LAN

    [计算机网络]-介质访问控制子层-无线LAN 802.11体系结构和协议栈 802.11网络使用模式: 有架构模式(Infrastructure mode) 无线客户端连接接入点AP,叫做有架构模式 ...

  3. # Pycharm打造高效Python IDE

    Pycharm打造高效Python IDE 建议以scientific mode运行,在科学计算时,可以方便追踪变量变化,并且会提示函数的用法,比普通模式下的提示更加智能,一般在文件中引入了numpy ...

  4. Redis5版本集群搭建

    一.简介 1.1 Redis是什么 Redis是一个开源的,使用ANSI C 编写,高性能的Key-Value的NoSQL数据库. 1.2 Redis特点 (1)基于内存 (2)可持久化数据 (3)具 ...

  5. 07 Python中zip(),map(),filter(),reduce()用法

    一. zip() zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表. 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 ...

  6. Spring Boot整合actuator实现监控管理

    Spring Boot使用actuator监控管理 1.在pom文件中导入相关的依赖 <dependency> <groupId>org.springframework.boo ...

  7. postgres日常操作

    1.启动pgsl数据库 [postgres@master ~]$ pg_ctl start [postgres@master data]$ pg_ctl -D /usr/local/pgsql/dat ...

  8. JS异步上传文件

    直接调用Upload(option)方法,即可上传文件,不需要额外的插件辅助,采用原生js编写. /* *异步上传文件 *option参数 **url:上传路径 **data:上传的其他数据{id:& ...

  9. Redis位操作介绍

    在学习redis的过程了,看到了redis还能用于大数据处理,具体场景如下:腾讯10亿用户,要几个毫秒内查询到某个用户是否在线,你能怎么做?千万别说给每个用户建立一个key,然后挨个记(你可以算一下需 ...

  10. 可执行程序加一个dl

    add_executable(forwarder app/main.cxx) TARGET_LINK_LIBRARIES(forwarder dl)