题解

一道非常神仙的计数题
如果只有一个点,就是非常简单的树型dp

\(f_{u} = (siz_{u} - 1)! \prod_{v \in son_{u}} \frac{f_{v}}{siz_{v}!}\)
\(\frac{f_{u}}{siz_{u}!} = \frac{1}{siz_{u}} \prod_{v \in son_{u}} \frac{f_{v}}{siz_{v}!}\)
\(f_{u} = \frac{n!}{\prod s_{i}}\)

可是我们有两个点,我们把这两个点连起来的点作为第一个黑点的话,这就是一个环套树,把环拎出来,我们枚举在哪里断开

我们设环长为m,添加上的黑点即\(v_0\)同时\(v_0\)和\(v_m\)相连

这样的话,如果我们要让\(v_{i}\)是最后一个被染红的,那么不在环上的点的子树大小都不会改变
我们断开\(v_{i} - v_{i + 1}\)和\(v_{i - 1} - v_{i}\)都可以
也就是说,我们断开一条边,对应着两个点被最后一个染色的方案数
总共计算了两遍,我们最后的答案除二就行

现在,我们把问题转化成了,枚举断开的一条边,把图变成一棵树,求这棵树的方案数,即套用我们所求的公式,需要的就是快速算出环上的点的子树大小更新的情况

我们用\(s_{i}\)表示第i个点上所挂的树的大小,并把这个东西处理成一个前缀和
我们对于每个点,它的值是
\(\prod_{i \neq j } (s_{i} - s_{j})\)
我们要求的是
\(\sum_{i} \prod_{i \neq q} (s_{i} - s_{j})\)
我们如果把\(s_{i}\)设成变量,那么
\(\sum_{i} \prod_{i \neq q} (x- s_{j})\)这个式子可以联系到导数
也就是
\(\sum_{i} \prod_{i \neq q} (x - s_{j}) = \frac{\mathrm{d} }{\mathrm{d} x} \prod (x - s_{i})\)
然后我们直接多项式插值就可以了

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <ctime>
#include <map>
#include <set>
#define fi first
#define se second
#define pii pair<int,int>
//#define ivorysi
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define MAXN 234600
using namespace std;
typedef long long int64;
typedef double db;
typedef unsigned int u32;
template<class T>
void read(T &res) {res = 0;T f = 1;char c = getchar();while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9' ) {res = res * 10 - '0' + c;c = getchar();}res *= f;
}
template<class T>
void out(T x) {if(x < 0) {x = -x;putchar('-');}if(x >= 10) {out(x / 10);}putchar('0' + x % 10);
}const int MOD = 998244353;
int W[(1 << 20) + 5];
int mul(int a,int b) {return 1LL * a * b % MOD;
}
int inc(int a,int b) {return a + b >= MOD ? a + b - MOD : a + b;
}
int fpow(int x,int c) {int res = 1,t = x;while(c) {if(c & 1) res = mul(res,t);t = mul(t,t);c >>= 1;}return res;
}
struct node {int to,next;
}E[MAXN * 2];
int head[MAXN],sumE,N,A,B,siz[MAXN],fa[MAXN],sum[MAXN],tot,fac,inv[MAXN];
int ans[MAXN];
void add(int u,int v) {E[++sumE].to = v;E[sumE].next = head[u];head[u] = sumE;
}
void dfs(int u) {siz[u] = 1;for(int i = head[u] ; i ; i = E[i].next) {int v = E[i].to;if(v != fa[u]) {fa[v] = u;dfs(v);siz[u] += siz[v];}}
}
struct poly {vector<int> p;poly() {p.clear();}void print() {for(int i = 0 ; i < p.size() ; ++i) {out(p[i]);space;}enter;}friend void NTT(poly &f,int L,int on) {f.p.resize(L);for(int i = 1, j = L / 2 ; i < L - 1 ; ++i) {if(i < j) swap(f.p[i],f.p[j]);int k = L / 2;while(j >= k) {j -= k;k >>= 1;}j += k;}for(int h = 2 ; h <= L ; h <<= 1) {int wn = W[((1 << 20) + on * (1 << 20) / h) % (1 << 20)];for(int k = 0 ; k < L ; k += h) {int w = 1;for(int j = k ; j < k + h / 2 ; ++j) {int u = f.p[j],t = mul(w,f.p[j + h / 2]);f.p[j] = inc(u,t);f.p[j + h / 2] = inc(u,MOD - t);w = mul(w,wn);}}}if(on == -1) {int InvL = fpow(L,MOD - 2);for(int i = 0 ; i < L ; ++i) {f.p[i] = mul(f.p[i],InvL);}}}friend poly operator * (poly f,poly g) {int L = f.p.size() + g.p.size();int t = 1;while(t <= L) t <<= 1;poly h;h.p.resize(t);NTT(f,t,1);NTT(g,t,1);for(int i = 0 ; i < t ; ++i) {h.p[i] = mul(f.p[i],g.p[i]);}NTT(h,t,-1);for(int i = t - 1 ; i >= 0; --i) {if(h.p[i] == 0) h.p.pop_back();else break;}return h;}friend poly operator + (poly f,poly g) {poly h;int t = max(f.p.size(),g.p.size());f.p.resize(t);g.p.resize(t);for(int i = 0 ; i < t ; ++i) {h.p.pb(inc(f.p[i],g.p[i]));}for(int i = t - 1; i >= 0 ; --i) {if(!h.p[i]) h.p.pop_back();else break;}return h;}friend poly operator - (poly f,poly g) {poly h;int t = max(f.p.size(),g.p.size());f.p.resize(t);g.p.resize(t);for(int i = 0 ; i < t ; ++i) {h.p.pb(inc(f.p[i],MOD - g.p[i]));}for(int i = t - 1; i >= 0 ; --i) {if(!h.p[i]) h.p.pop_back();else break;}return h;}friend poly Inverse(poly f,int L) {poly g,r,two;two.p.pb(2);g.p.pb(fpow(f.p[0],MOD - 2));r.p.pb(f.p[0]);int t = 1;while(t <= L) {int m = min(t * 2,(int)f.p.size());for(int i = t ; i < m ; ++i) {r.p.pb(f.p[i]);}t = t * 2;g = g * (two - r * g);int tmp = g.p.size();for(int i = tmp - 1; i >= t ; --i) g.p.pop_back();}t = g.p.size();for(int i = t - 1 ; i >= L ; --i) g.p.pop_back();t = L - 1;for(int i = t ; i >= 0 ; --i) {if(!g.p[i]) g.p.pop_back();else break;}return g;}friend poly operator / (poly f,poly g) {reverse(f.p.begin(),f.p.end());reverse(g.p.begin(),g.p.end());int t = f.p.size() - g.p.size() + 1;poly h = Inverse(g,t);poly q = f * h;for(int i = q.p.size() - 1 ; i >= t ; --i) q.p.pop_back();reverse(q.p.begin(),q.p.end());for(int i = t - 1 ; i >= 0 ; --i) {if(!q.p[i]) q.p.pop_back();else break;}return q;}friend poly operator % (poly f,poly g) {return f - g * (f / g);}
};
poly tr[MAXN * 4];
poly Solve1(int u,int l,int r) {if(l == r) {tr[u].p.pb(MOD - sum[l]);tr[u].p.pb(1);return tr[u];}int mid = (l + r) >> 1;tr[u << 1] = Solve1(u << 1,l,mid);tr[u << 1 | 1] = Solve1(u << 1 | 1,mid + 1,r);return tr[u] = tr[u << 1] * tr[u << 1 | 1];
}
void Solve2(int u,int l,int r,poly f) {if(l == r) {if(!f.p.size()) ans[l] = 0;else ans[l] = f.p[0];return;}int mid = (l + r) >> 1;Solve2(u << 1,l,mid,f % tr[u << 1]);Solve2(u << 1 | 1,mid + 1,r,f % tr[u << 1 | 1]);
}
void Init() {W[0] = 1;W[1] = fpow(3,(MOD - 1) / (1 << 20));for(int i = 2 ; i < (1 << 20) ; ++i) {W[i] = mul(W[i - 1],W[1]);}read(N);read(A);read(B);int x,y;for(int i = 1 ; i < N ; ++i) {read(x);read(y);add(x,y);add(y,x);}dfs(A);int f = B,t = 0;fac = 1;while(t != A) {sum[++tot] = siz[f] - siz[t];fac = mul(fac,siz[f]);t = f;f = fa[f];}for(int i = 1 ; i <= tot ; ++i) sum[i] += sum[i - 1];inv[1] = 1;for(int i = 2 ; i <= N; ++i) {inv[i] = mul(inv[MOD % i],MOD - MOD / i);fac = mul(fac,i);}for(int i = 1 ; i <= N ; ++i) fac = mul(fac,inv[siz[i]]);}
void Solve() {poly f = Solve1(1,0,tot);int t = f.p.size();for(int i = 0 ; i < t - 1 ; ++i) {f.p[i] = mul(f.p[i + 1],i + 1);}f.p.pop_back();Solve2(1,0,tot,f);int tmp = 1;for(int i = tot ; i >= 0 ; --i) {ans[i] = mul(ans[i],tmp);tmp = mul(tmp,MOD - 1);}tmp = 0;for(int i = 0 ; i <= tot ; ++i) {tmp = inc(tmp,fpow(ans[i],MOD - 2));}fac = mul(fac,tmp);fac = mul(fac,inv[2]);out(fac);enter;
}
int main() {
#ifdef ivorysifreopen("f1.in","r",stdin);
#endifInit();Solve();return 0;
}

转载于:https://www.cnblogs.com/ivorysi/p/9410641.html

【LOJ】#6391. 「THUPC2018」淘米神的树 / Tommy相关推荐

  1. loj 3090 「BJOI2019」勘破神机 - 数学

    题目传送门 传送门 题目大意 设$F_{n}$表示用$1\times 2$的骨牌填$2\times n$的网格的方案数,设$G_{n}$$表示用$1\times 2$的骨牌填$3\times n$的网 ...

  2. LOJ 3090 「BJOI2019」勘破神机——斯特林数+递推式求通项+扩域

    题目:https://loj.ac/problem/3090 题解:https://www.luogu.org/blog/rqy/solution-p5320 1.用斯特林数把下降幂化为普通的幂次求和 ...

  3. [loj6391][THUPC2018]淘米神的树(Tommy)

    前言 经典板子应用题 题目相关 链接 题目大意 现在有一个nnn个节点的树,初始nnn个节点有n−2n-2n−2个是白色的,222个是黑色的 每次可以将一个黑点染红,并将相邻的白点同时染黑 问把整棵树 ...

  4. LOJ 2339 「WC2018」通道——边分治+虚树

    题目:https://loj.ac/problem/2339 两棵树的话,可以用 CTSC2018 暴力写挂的方法,边分治+虚树.O(nlogn). 考虑怎么在这个方法上再加一棵树.发现很难弄. 看了 ...

  5. LOJ 3055 「HNOI2019」JOJO—— kmp自动机+主席树

    题目:https://loj.ac/problem/3055 先写了暴力.本来想的是 n<=300 的那个在树上暴力维护好整个字符串, x=1 的那个用主席树维护好字符串和 nxt 数组.但 x ...

  6. 【LOJ】#3090. 「BJOI2019」勘破神机

    LOJ#3090. 「BJOI2019」勘破神机 为了这题我去学习了一下BM算法.. 很容易发现这2的地方是\(F_{1} = 1,F_{2} = 2\)的斐波那契数列 3的地方是\(G_{1} = ...

  7. Loj #3089. 「BJOI2019」奥术神杖

    Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...

  8. Loj #3111. 「SDOI2019」染色

    Loj #3111. 「SDOI2019」染色 题目描述 给定 \(2 \times n\) 的格点图.其中一些结点有着已知的颜色,其余的结点还没有被染色.一个合法的染色方案不允许相邻结点有相同的染色 ...

  9. 【LibreOJ】#6395. 「THUPC2018」城市地铁规划 / City 背包DP+Prufer序

    [题目]#6395. 「THUPC2018」城市地铁规划 / City [题意]给定n个点要求构造一棵树,每个点的价值是一个关于点度的k次多项式,系数均为给定的\(a_0,...a_k\),求最大价值 ...

  10. Loj #3055. 「HNOI2019」JOJO

    Loj #3055. 「HNOI2019」JOJO JOJO 的奇幻冒险是一部非常火的漫画.漫画中的男主角经常喜欢连续喊很多的「欧拉」或者「木大」. 为了防止字太多挡住漫画内容,现在打算在新的漫画中用 ...

最新文章

  1. 重磅!苹果祭出大招:史上最强 Mac 发布,iPad OS 惊艳问世
  2. 模拟用户登陆Web应用
  3. docker 安装 nacos/nacos-server 镜像并配置本地数据库
  4. Leedcode7-binary-tree-postorder-traversal
  5. STM32 输入捕获功能
  6. python 引用文件中的类 报错_Python学习笔记7 头文件的添加规则(转载)
  7. POJ 2828Buy Tickets
  8. 拒绝空谈 AI 设想!手把手教你构建实时、高可用的 AI 调度平台
  9. JAVA操作文件大全(一)
  10. 看了看几个数据库厂商的发展历史
  11. 光敏传感器实验报告_光敏传感器光电特性研究实验报告.docx
  12. 头歌-离散数学(python)-关系运算
  13. 手把手教你在Linux系统进行项目部署
  14. 苹果电脑一直密码错误_您可能一直都在犯的安全和密码错误
  15. 金蝶KIS标准迷你版专业版 K3 引出报表提示保存文件失败,原因:Automation错误
  16. 解决百度网盘限速超简单
  17. Emacs学习使用之路(一)
  18. 护眼灯真的可以保护眼睛吗?市面上的护眼台灯到底是不是智商税
  19. 两周年无人问津,EOS到底做错了什么
  20. GROMACS Tutorial 1-Lysozyme in Water-translated with notes

热门文章

  1. 程序员如何让自己 Be Cloud Native - 配置篇 1
  2. Mysql 5.7 Gtid内部学习(八) Gtid带来的运维改变
  3. Java容器类研究8:HashMap
  4. SSM框架整合_1MyBatis搭建
  5. 超全面的JavaWeb笔记day11JSPSessionCookieHttpSession
  6. oracle 切换用户操作--or--sys用户密码忘记
  7. c#对PL/SQL查询结果列复制的结果生成指定格式
  8. jQuery---仿芒果网机票预定智能输入提示.
  9. [HTML] Prettify 代码高亮使用总结
  10. [2018.10.20 T3] 巧克力