题面传送门

没错这就是我 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. Less-25 preg_replace2

    Less-25: 核心语句: 各种回显也均有. 通过blacklist,我们可以发现,本题屏蔽了and和or. preg_replace函数中正则表达式后面的i是一个修饰符,代表正则匹配时不区分大小写 ...

  2. Scrum Meeting 0607

    零.说明 日期:2021-6-7 任务:简要汇报两日内已完成任务,计划后两日完成任务 一.进度情况 组员 负责 两日内已完成的任务 后两日计划完成的任务 困难 qsy PM&前端 重新设计产品 ...

  3. C/C++中浮点数输出精度的问题

    本文使用C++语言书写,对于C的小伙伴们,如果编译不通过的话--就说明C里面没有这个内容,可以跳过 通常来说,我们书写程序主要只用整形变量 (signed/unsigned) (long/long l ...

  4. 常用Java API: ArrayList(Vector) 和 LinkedList

    摘要: 本文主要介绍ArrayList(Vector)和LinkedList的常用方法, 也就是动态数组和链表. ArrayList ArrayList 类可以实现可增长的对象数组. 构造方法 Arr ...

  5. Netty:Netty中的零拷贝(Zero Copy)

    零复制概念: " 零复制"描述了计算机操作,其中CPU不执行将数据从一个存储区复制到另一个存储区的任务.通过网络传输文件时,通常用于节省CPU周期和内存带宽. WIKI的定义中,我 ...

  6. PHP笔记1__基础知识

    客户端: 美妙的网页组成(都是由浏览器解释): 1.HTML 2.CSS--给HTML化妆 3.客户端脚本编程语言(JavaScript等)--特效  服务器端: 1.Web服务器Apache/Ngi ...

  7. mininet-2.2.2-170321-ubuntu-14.04.4-server-amd64的使用

    1.使用Vmware打开下载好的mininet-2.2.2-170321-ubuntu-14.04.4-server-amd64 2.登录账号密码都为mininet 3.用命令行生成拓扑,并测试连通性 ...

  8. PHP怎样写延时队列(定时器)

    背景 PHP没有定时器,依托的都是crontab这样的系统工具,也没有go中defer这样的延时方法,本文介绍几种PHP写延时队列的几种姿势. 延时队列的定义 普通的队列是先进先出,但是延时队列并不是 ...

  9. Haar小波的理解

    1. 首先理解L^2(R)的概念 L^2(R) 是一个内积空间的概念,表示两个无限长的向量做内积,张成的空间问题.也就是两个函数分别作为一个向量,这两个函数要是平方可积的.L^2(a,b)=<f ...

  10. JavaScript事件捕获冒泡与捕获

    事件流 JavaScript中,事件流指的是DOM事件流. 概念 事件的传播过程即DOM事件流.事件对象在 DOM 中的传播过程,被称为"事件流".举个例子:开电脑这个事,首先你是 ...