[CTS2019]氪金手游(容斥+树形背包DP)

降智好题。本蒟蒻VP时没想到怎么做被题面迷惑了,只会20分的“好”成绩。简直自闭了。

首先显然度为0的点是白给的,根据等比数列求和公式即可求得。然后考虑这个树如果是一颗外向树,就是每个点先父亲再自己。然后直接DP,令f[i][j]表示子树i内Σw=j的概率,转移时直接用背包转移一发即可。边是正向的直接转移,反向的加上去掉该限制的答案,并减去反向的答案。复杂度显然是O(n2)

#include<bits/stdc++.h>
using namespace std;
const int N=1019,mod=998244353;
int n,cnt,ans,p[N][4],f[N][N*3],g[N*3],sz[N],inv[N*3],hd[N],v[N<<1],nxt[N<<1],w[N<<1];
void add(int&x,int y){x=x+y>=mod?x+y-mod:x+y;}
int qpow(int a,int b)
{
    int ret=1;
    while(b)
    {
        if(b&1)ret=1ll*ret*a%mod;
        a=1ll*a*a%mod,b>>=1;
    }
    return ret;
}
void adde(int x,int y)
{
    v[++cnt]=y,w[cnt]=1,nxt[cnt]=hd[x],hd[x]=cnt;
    v[++cnt]=x,w[cnt]=0,nxt[cnt]=hd[y],hd[y]=cnt;
}
void dfs(int u,int fa)
{
    f[u][0]=1;
    for(int i=hd[u];i;i=nxt[i])
    if(v[i]!=fa)
    {
        dfs(v[i],u);
        for(int j=0;j<=sz[u]+sz[v[i]];j++)g[j]=0;
        for(int j=0;j<=sz[u];j++)
        for(int k=0;k<=sz[v[i]];k++)
        {
            int val=1ll*f[u][j]*f[v[i]][k]%mod;
            if(w[i])add(g[j+k],val);else add(g[j+k],mod-val),add(g[j],val);
        }
        sz[u]+=sz[v[i]];
        for(int j=0;j<=sz[u];j++)f[u][j]=g[j];
    }
    memset(g,0,sizeof g);
    for(int i=0;i<=sz[u];i++)
    for(int j=1;j<=3;j++)
    add(g[i+j],1ll*f[u][i]*p[u][j]%mod*j%mod*inv[i+j]%mod);
    sz[u]+=3;
    for(int i=0;i<=sz[u];i++)f[u][i]=g[i];
}
int main()
{
    scanf("%d",&n);
    for(int i=1,x,y,z,sum;i<=n;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        sum=qpow(x+y+z,mod-2);
        p[i][1]=1ll*x*sum%mod,p[i][2]=1ll*y*sum%mod,p[i][3]=1ll*z*sum%mod;
    }
    inv[0]=inv[1]=1;for(int i=2;i<=n*3;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),adde(x,y);
    dfs(1,0);
    for(int i=0;i<=3*n;i++)add(ans,f[1][i]);
    printf("%d",ans);
}

原文地址:https://www.cnblogs.com/hfctf0210/p/10901589.html

时间: 2024-07-29 07:56:57

[CTS2019]氪金手游(容斥+树形背包DP)的相关文章

Luogu5405 CTS2019氪金手游(容斥原理+树形dp)

考虑外向树怎么做.显然设f[i][j]为i子树中出现权值和为j的合法方案的概率,转移做树形背包即可. 如果树上只有一条反向边,显然可以先不考虑该边计算概率,再减去将整棵树看做外向树的概率.于是考虑容斥,进一步拓展到多条反向边,就是考虑0条反向边的概率-考虑1条反向边的概率+考虑2条反向边的概率……容斥可以在dp中完成,即遇到反向边时分是否考虑它转移,若考虑乘上-1的系数. #include<bits/stdc++.h> using namespace std; #define ll long

p5405 [CTS2019]氪金手游

题目大意 题意狗屁不通 看毛子语都比看这个题面强 分析 我们假设这棵树是一个内向树 那么我们可以轻易的得到dp[x][i]表示x点子树和为i的期望 转移只需枚举当前期望大小和子树期望大小即可 但是由于边的方向不一定 所以这棵树上存在反向边 我们可以容斥有i个边不合法的情况 因此对于一个反向边要么x点加上关系合法,将子树分离的贡献 要么这个边算是不合法的 对于这种情况我们可以直接减掉贡献 因为我们知道这个贡献已经是0~i的容斥情况 而这个减号相当于*-1 可以完成容斥 复杂度O(n^2) 代码 #

hdu1561:树形背包dp

给定n个地点,每个地点藏有cost[i]的宝物,取得某些宝物有时需要先取其他宝物,现在让我们选m个地点问最多可以选多少宝物? 还是挺裸的树形背包dp吧,不难,关键还是中间dp的部分.可以做模板了->_-> 注意点:多组数据的话如果第一组对了然后其他都错了,那么很有可能是初始化的时候漏了.这次找可很久才知道差了e[0].clear().平时的习惯都是从1开始. --------------------------------------------------------------------

【bzoj4987】Tree 树形背包dp

题目描述 从前有棵树. 找出K个点A1,A2,…,Ak. 使得∑dis(AiAi+1),(1<=i<=K-1)最小. 输入 第一行两个正整数n,k,表示数的顶点数和需要选出的点个数. 接下来n-l行每行3个非负整数x,y,z,表示从存在一条从x到y权值为z的边. I<=k<=n. l<x,y<=n 1<=z<=10^5 n <= 3000 输出 一行一个整数,表示最小的距离和. 样例输入 10 7 1 2 35129 2 3 42976 3 4 244

NYOJ 674 善良的国王(树形背包DP)

善良的国王 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 传说中有一个善良的国王Good,他为了不劳民伤财,每当建造一个城镇的时候都只用一条路去连接,这样就可以省很多的人力和物力,也就说如果有n个城镇,那么只需要n-1条路就可以把所有的城镇链接起来了(也就是一颗树了).但是不幸的事情发生了:有个一强大的帝国想要占领这个国家,但是由于国王Good的兵力不足,只能守护m个城镇,所以经过商量,国王Good只能从他的所有城镇中选择m个相链接的城市,并且把所有可以链接到这m

【bzoj4753】[Jsoi2016]最佳团体 分数规划+树形背包dp

题目描述 JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号.每个候选人都由一位编号比他小的候选人Ri推荐.如果Ri=0则说明这个候选人是JYY自己看上的.为了保证团队的和谐,JYY需要保证,如果招募了候选人i,那么候选人Ri"也一定需要在团队中.当然了,JYY自己总是在团队里的.每一个候选人都有一个战斗值Pi",也有一个招募费用Si".JYY希望招募K个候选人(JYY自己不算),组成一个性价比最高的团队.也就是,这K个被JYY选择的候

【bzoj1495】[NOI2006]网络收费 暴力+树形背包dp

题目描述 给出一个有 $2^n$ 个叶子节点的完全二叉树.每个叶子节点可以选择黑白两种颜色. 对于每个非叶子节点左子树中的叶子节点 $i$ 和右子树中的叶子节点 $j$ :如果 $i$ 和 $j$ 的颜色都为当前节点子树中颜色较多(相等视为白色)的那个,则不需要付出代价:都为较小的那个则需要付 $2f[i][j]$ 的代价:否则需要付 $f[i][j]$ . 求最小代价. 输入 输入文件中第一行有一个正整数N. 第二行有2N个整数,依次表示1号,2号,…,2N号用户注册时的付费方式,每一个数字若

P2014 选课 - 树形DP[树形背包DP]

P2014 选课 传送门 思路: 树形背包DP模型,\(f[i,j]\)表示以\(i\)为根的子树中,选了\(j\)门课的最大学分.树形DP常以子树\(i\)为阶段.树形背包DP相当于树上分组背包DP.\(f[u,j]=max\{f[u,j],f[u,j-k]+f[v,k]~|~v\in~son(u)\}\).我们枚举从u的子树v中选的课数k,将\(f[v,k]\)作为获得的价值加到\(f[u,j-k]\)得到\(f[u,j]\).注意到当前子树根节点u是必须选的,所以要从\(f[u,j-1]\

20191110luogu3698小Q的棋盘 | 树形背包dp | 贪心

luogu3698小Q的棋盘 题意: 求从树的根节点出发,走n步能经过的最多的点的数量(可以重复走点,但是重复走的步数会记录) 树形背包dp: 对于从0出发,我们可以这样走: 1.选一条岔路一直走下去 2.选一条岔路走后回到0点,再选一条岔路走下去 对应的dp转移: f[0][u][j]代表从u出发走j步不一定回到u点能到达的最大步数 f[1][u][j]代表从u出发走j步回到u点能到达的最大步数 f[0][u][j] = max(f[0][u][j],f[0][u][k] + f[1][too