题面传送门

没错这就是我 boom0 的那场 NOIOL 的 T3

一年前,我在 NOIOL #2 的赛场上折戟沉沙,一年后,我从倒下的地方爬起。

我成功了,我不再是从前那个我了

我们首先假设 A 拥有的点为 \(p_1,p_2,\cdots,p_m\),B 拥有的点为 \(q_1,q_2,\cdots,q_m\),显然 A、B 出牌的顺序是无关紧要的,因此我们不妨假设 A 就按 \(p_1,p_2,\cdots,p_m\) 的顺序出牌,题目就等价于有多少个 \(q\) 的排列 \(r\) 满足恰好存在 \(k\) 对 \((p_i,r_i)\) 是祖先关系。

其次,注意到这个“恰好”非常难受,因为它既包含匹配也包含不匹配的情况,而这两种情况是很难在一起考虑的。

这时候我们就可以很自然地想到一个套路叫“二项式反演”,我们考虑任意钦定 \(k\) 对必须匹配的点,即记 \(f_k\) 为钦定 \(k\) 对必须匹配的点,剩余随便排列的方案数,再记 \(g_k\) 为恰好存在 \(k\) 对 \((p_i,r_i)\) 是祖先关系的方案数。那么有 \(f_k=\sum\limits_{i=k}\dbinom{i}{k}g_i\),反演以下即可 \(g_k=\sum\limits_{i=k}\dbinom{i}{k}(-1)^{i-k}f_i\)。

接下来考虑怎样求 \(f_i\),这显然是一个简单的树形背包问题,设 \(dp_{u,j}\) 表示 \(u\) 的子树内钦定了 \(j\) 对要匹配的点的方案数。考虑转移,我们首先按照树形背包的套路将 \(u\) 所有子树的 \(dp\) 值合并起来,合并完之后的 \(dp_{u,j}\) 的显然就是在 \(u\) 所有儿子的子树中钦定 \(j\) 对需匹配的点的方案数,此时我们还需再考虑 \(u\) 的匹配情况,如果 \(u\) 属于 A,那么我们令 \(dp_{u,j+1}\leftarrow dp_{u,j}\times(c1_u-j)\),其中 \(c1_u\) 表示 \(u\) 子树内有多少个点属于 B,\(u\) 属于 B 的情况也同理,注意,这里的 \(j\) 需要倒序枚举。最终 \(f_k=dp_{1,k}\times(\dfrac{n}{2}-k)!\)。

时间复杂度 \(\mathcal O(n^2)\)

总之当时觉得这道题是道 dlt,现在看来,也就 just so so 罢(

const int MAXN=5e3;
const int MOD=998244353;
char s[MAXN+5];
int n,c0[MAXN+5],c1[MAXN+5],dp[MAXN+5][MAXN+5];
int hd[MAXN+5],to[MAXN*2+10],nxt[MAXN*2+10],ec=0;
void adde(int u,int v){to[++ec]=v;nxt[ec]=hd[u];hd[u]=ec;}
int tmp[MAXN+5];
void dfs(int x,int f){
dp[x][0]=1;
for(int e=hd[x];e;e=nxt[e]){
int y=to[e];if(y==f) continue;dfs(y,x);
memset(tmp,0,sizeof(tmp));
for(int u=0;u<=min(c0[x],c1[x]);u++)
for(int v=0;v<=min(c0[y],c1[y]);v++){
tmp[u+v]=(tmp[u+v]+1ll*dp[x][u]*dp[y][v])%MOD;
}
c0[x]+=c0[y];c1[x]+=c1[y];
for(int u=0;u<=min(c0[x],c1[x]);u++) dp[x][u]=tmp[u];
}
if(s[x]=='0'){
for(int u=min(c0[x],c1[x]);~u;u--){
dp[x][u+1]=(dp[x][u+1]+1ll*dp[x][u]*(c1[x]-u))%MOD;
} c0[x]++;
} else {
for(int u=min(c0[x],c1[x]);~u;u--){
dp[x][u+1]=(dp[x][u+1]+1ll*dp[x][u]*(c0[x]-u))%MOD;
} c1[x]++;
}
// for(int u=0;u<=min(c0[x],c1[x]);u++) printf("%d %d %d\n",x,u,dp[x][u]);
}
int fac[MAXN+5],ifac[MAXN+5];
void init_fac(int n){
for(int i=(fac[0]=ifac[0]=ifac[1]=1)+1;i<=n;i++) ifac[i]=1ll*ifac[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%MOD,ifac[i]=1ll*ifac[i-1]*ifac[i]%MOD;
}
int binom(int n,int k){return 1ll*fac[n]*ifac[k]%MOD*ifac[n-k]%MOD;}
int f[MAXN+5],g[MAXN+5];
int main(){
scanf("%d%s",&n,s+1);
for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),adde(u,v),adde(v,u);
dfs(1,0);init_fac(n);
for(int i=0;i<=n/2;i++) f[i]=1ll*fac[n/2-i]*dp[1][i]%MOD;
for(int i=0;i<=n/2;i++){
for(int j=i;j<=n/2;j++){
if((j-i)&1) g[i]=(g[i]-1ll*binom(j,i)*f[j]%MOD+MOD)%MOD;
else g[i]=(g[i]+1ll*binom(j,i)*f[j])%MOD;
} printf("%d\n",g[i]);
}
return 0;
}

洛谷 P6478 - [NOI Online #2 提高组] 游戏(二项式反演+树形 dp)的更多相关文章

  1. 洛谷 P6570 - [NOI Online #3 提高组] 优秀子序列(集合幂级数+多项式)

    洛谷题面传送门 首先 \(3^n\) 的做法就不多说了,相信对于会状压 dp+会枚举子集的同学来说不算困难(暴论),因此这篇博客将着重讲解 \(2^nn^2\) 的做法. 首先如果我们把每个 \(a_ ...

  2. 洛谷P1003 铺地毯 noip2011提高组day1T1

    洛谷P1003 铺地毯 noip2011提高组day1T1 洛谷原题 题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n ...

  3. 洛谷-神奇的幻方-NOIP2015提高组复赛

    题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,--,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...

  4. 洛谷 P1541 乌龟棋 & [NOIP2010提高组](dp)

    传送门 解题思路 一道裸的dp. 用dp[i][j][k][kk]表示用i个1步,j个2步,k个3步,kk个4步所获得的最大价值,然后状态转移方程就要分情况讨论了(详见代码) 然后就是一开始统计一下几 ...

  5. 洛谷 P1525 关押罪犯 & [NOIP2010提高组](贪心,种类并查集)

    传送门 解题思路 很显然,为了让最大值最小,肯定就是从大到小枚举,让他们分在两个监狱中,第一个不符合的就是答案. 怎样判断是否在一个监狱中呢? 很显然,就是用种类并查集. 种类并查集的讲解——团伙(很 ...

  6. 洛谷 P5019 铺设道路 & [NOIP2018提高组](贪心)

    题目链接 https://www.luogu.org/problem/P5019 解题思路 一道典型的贪心题. 假设从左往右填坑,如果第i个深与第i+1个,那么第i+1个就不需要额外填: 如果第i+1 ...

  7. 洛谷P1063 能量项链 [2006NOIP提高组]

    P1063 能量项链 题目描述 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标 记的珠子,这些标记对应着某个正整数.并且,对于相邻的两颗珠子 ...

  8. 「洛谷P1080」「NOIP2012提高组」国王游戏 解题报告

    P1080 国王游戏 题目描述 恰逢 \(H\)国国庆,国王邀请\(n\)位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 \( ...

  9. bzoj 2005 & 洛谷 P1447 [ Noi 2010 ] 能量采集 —— 容斥 / 莫比乌斯反演

    题目:bzoj 2005 https://www.lydsy.com/JudgeOnline/problem.php?id=2005   洛谷 P1447 https://www.luogu.org/ ...

随机推荐

  1. jdbc简单学生管理系统

    这个是java连接mysql数据库的一个简单学生系统,通过jdbc连接数据库. 工具类 JDBCuntils. package Student; import java.io.IOException; ...

  2. 三分钟极速体验:Java版人脸检测

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  3. 【UE4 C++ 基础知识】<6> 容器——TMap

    概述 TMap主要由两个类型定义(一个键类型和一个值类型),以关联对的形式存储在映射中. 将数据存储为键值对(TPair<KeyType, ValueType>),只将键用于存储和获取 映 ...

  4. Java:并发笔记-03

    Java:并发笔记-03 说明:这是看了 bilibili 上 黑马程序员 的课程 java并发编程 后做的笔记 3. 共享模型之管程-2 本章内容-2 Monitor wait/notify 3.6 ...

  5. [no code][scrum meeting] Alpha 12

    项目 内容 会议时间 2020-04-19 会议主题 周总结会议 会议时长 45min 参会人员 全体成员 $( "#cnblogs_post_body" ).catalog() ...

  6. 线程池系列二:一张动图,彻底懂了execute和submit

    ​ 我们知道线程池通过execute方法执行提交的Runnable任务,但Runnable只是执行任务,没有返回任何信息. [线程池原理:线程池原来是个外包公司,打工人我悟了] 若是我们想在异步执行完 ...

  7. Android DataBinding使用详解

    简介 DataBinding是一个自动绑定UI的框架. 使用DataBinding需要在app根目录的build.gradle文件中加入DataBinding配置: android { .... da ...

  8. 面试官:能用JS写一个发布订阅模式吗?

    目录 1 场景引入 2 代码优化 2.1 解决增加粉丝问题 2.2 解决添加作品问题 3 观察者模式 4 经纪人登场 5 发布订阅模式 6 观察者模式和发布订阅模式的对比 什么是发布订阅模式?能手写实 ...

  9. Docker 搭建 Jenkins 持续集成自动化构建环境

    1.Docker镜像拉取 Jenkins 环境命令 docker pull jenkins/jenkins:lts 查看下拉取的镜像 docker images 2.通过容器编排方式构建 Jenkin ...

  10. Openssl基本组成与应用

    SSL与Openssl有什么关系? ssl是一种应用,表示安全的套接字层,是为那些明文应用提供加密机制的应用,openssl是一个实现该协议的库,当然还实现了其他很多东西,并且是open source ...