[LOJ3124][CTS2019|CTSC2019]氪金手游:树形DP+概率DP+容斥原理
分析
首先容易得出这样一个事实,在若干物品中最先被选出的是编号为\(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+容斥原理的更多相关文章
- 「CTS2019」氪金手游
「CTS2019」氪金手游 解题思路 考场上想出了外向树的做法,居然没意识到反向边可以容斥,其实外向树会做的话这个题差不多就做完了. 令 \(dp[u][i]\) 表示单独考虑 \(u\) 节点所在子 ...
- 【CTS2019】氪金手游(动态规划)
[CTS2019]氪金手游(动态规划) 题面 LOJ 洛谷 题解 首先不难发现整个图构成的结构是一棵树,如果这个东西是一个外向树的话,那么我们在意的只有这棵子树内的顺序关系,子树外的关系与这棵子树之间 ...
- [LibreOJ 3124]【CTS2019】氪金手游【容斥原理】【概率】【树形DP】
Description Solution 首先它的限制关系是一个树形图 首先考虑如果它是一个外向树该怎么做. 这是很简单的,我们相当于每个子树的根都是子树中最早出现的点,概率是容易计算的. 设DP状态 ...
- Loj #3124. 「CTS2019 | CTSC2019」氪金手游
Loj #3124. 「CTS2019 | CTSC2019」氪金手游 题目描述 小刘同学是一个喜欢氪金手游的男孩子. 他最近迷上了一个新游戏,游戏的内容就是不断地抽卡.现在已知: - 卡池里总共有 ...
- 「CTS2019 | CTSC2019」氪金手游 解题报告
「CTS2019 | CTSC2019」氪金手游 降 智 好 题 ... 考场上签到失败了,没想容斥就只打了20分暴力... 考虑一个事情,你抽中一个度为0的点,相当于把这个点删掉了(当然你也只能抽中 ...
- [CTS2019]氪金手游
[CTS2019]氪金手游 各种情况加在一起 先考虑弱化版:外向树,wi确定 i合法的概率就是wi/sw sw表示子树的w的和,和子树外情况无关 这些概率乘起来就是最终合法的概率 如果都是外向树, f ...
- SGU 495 Kids and Prizes:期望dp / 概率dp / 推公式
题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=495 题意: 有n个礼物盒,m个人. 最开始每个礼物盒中都有一个礼物. m个人依次随 ...
- LOJ3124 CTS2019 氪金手游 概率、容斥、树形DP
传送门 D2T3签到题可真是IQ Decrease,概率独立没想到然后就20pts滚粗了 注意题目是先对于所有点rand一个权值\(w\)然后再抽卡. 先考虑给出的关系是一棵外向树的情况.那么我们要求 ...
- LOJ 3124 「CTS2019 | CTSC2019」氪金手游——概率+树形DP
题目:https://loj.ac/problem/3124 看了题解:https://www.cnblogs.com/Itst/p/10883880.html 先考虑外向树. 考虑分母是 \( \s ...
随机推荐
- SpringMVC请求参数总结
前提 在日常使用SpringMVC进行开发的时候,有可能遇到前端各种类型的请求参数,这里做一次相对全面的总结.SpringMVC中处理控制器参数的接口是HandlerMethodArgumentRes ...
- Luogu P2617 Dynamic Rankings(整体二分)
题目 动态区间第K小模板题. 一个非常可行的办法是BIT套动态开点权值SegTree,但是它跑的实在太慢了. 然后由于这题并没有强制在线,所以我们可以使用整体二分来吊打树套树. 当然如果强制在线的话就 ...
- nginx+gunicorn/uwsgi+python web 的前世今生
我们在部署 flask.django 等 python web 框架时,网上最多的教程就是 nginx+gunicorn/uwsgi 的部署方式,那为什么要这么部署呢,本文就来系统地解释这个问题. 必 ...
- WPF中Brush类型
画刷Brush使用 画刷类 SolidColorBrush LinearGradientBrush RadialGradientBrush ImageBrush VisualBrush Drawing ...
- django自带登录认证与登录自动跳转
# 导入django自带模块 from django.contrib.auth import authenticate, login, logout # 使用authenticate进行认证,使用lo ...
- mysql设计与优化以及数据库表设计与表开发规范
一.设计问题? 1.主键是用自增还是UUID ? Innodb 中的主键是聚簇索引. 如果主键是自增的,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的 ...
- Vue-cli脚手架起步
1.安装node.js 下载地址:http://nodejs.cn/download/ 测试是否安装成功 node -V 检测安装包 npm -v 检测npm 2.安装webpack npm inst ...
- vue 组件基本使用
组件的基本使用 注册组件 注册组件就是利用Vue.component()方法,先传入一个自定义组件的名字,然后传入这个组件的配置.vue.component()注册的全局组件 Vue.componen ...
- python time,calendar,datetime
time sleep:休眠指定的秒数(可以是小数) localtime:将一个时间戳转换为time.struct_time类型的对象(类似于元组) # 将一个时间戳转换为一个类似于元组的对象,不指定时 ...
- docker删除虚悬镜像(临时镜像文件)
在我们构建镜像的过程中,常常需要使用build命令根据Dockerfile进行构建镜像,并且会build很多次,镜像名字也是相同的,那么就会出来下面这种情况