Codeforces Round #499 (Div. 1) F. Tree
Codeforces Round #499 (Div. 1) F. Tree
题目链接
\(\rm CodeForces\):https://codeforces.com/contest/1010/problem/F
Solution
设\(v_i\)表示第\(i\)个点的果子数,设\(b_i=v_i-\sum_{x\in son}v_x\),显然依题意要满足\(b_i\geqslant 0\)。
根据差分的性质我们可以得到\(\sum b_i=x\)。
假设我们硬点树上剩下了\(m\)个点,则根据插板法\(b_i\)的方案数为\(\displaystyle\binom{x+m-1}{m-1}\)。
由于\(b\)唯一确定\(v\),所以\(v\)的方案数也是这么多。
那么我们就考虑剩下\(m\)个点的方案数。
考虑一种暴力的\(dp\),设\(f[u][i]\)表示\(x\)子树保留了\(i\)个点(包括\(i\))的方案数,转移显然:
\]
写成生成函数就是:
\]
若\(u\)只有一个儿子也同理:
\]
若\(u\)为叶子则:
\]
证明显然。
考虑这个玩意怎么优化,显然如果\(\rm NTT\)优化复杂度\(O(n^2\log n)\),这是我们无法接受的。
我们考虑对这棵树进行轻重链剖分,那么对于一条重链上的每个点我们假设求出了非重儿子的\(F(x)\)。
那么我们对这条重链进行编号,从顶端到叶子为\(1\cdots c\),设\(a_i=xF_{son_i}(x)\)。
那么链顶的答案就是:
\]
我们递归的写完所有\(c\)个:
\]
暴力展开就是:
\]
这个可以分治\(\rm FFT\)解决,代码大概长这样:
void solve(int lt,int rt,vec &a,vec &b) {
if(lt==rt) return a=b=r[lt],void();
vec al,ar,bl,br;int mid=(lt+rt)>>1;solve(lt,mid,al,bl),solve(mid+1,rt,ar,br);
b=poly::pmul(bl,br);a=poly::padd(poly::pmul(ar,bl),al);
}
其中\(al,ar\)表示答案,\(bl,br\)表示区间乘积,其他的变量可以参考下下面的代码。
那么我们就解决了这个问题,因为总轻边的子树大小之和为\(O(n\log n)\),所以总复杂度为\(O(n\log ^3n)\)。
Code
#include<bits/stdc++.h>
using namespace std;
void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}
#define lf double
#define ll long long
#define pii pair<int,int >
#define vec vector<int >
#define pb push_back
#define mp make_pair
#define fr first
#define sc second
#define _sz(x) ((int)x.size())
#define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++)
const int maxn = 1<<19|10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 998244353;
int add(int x,int y) {return x+y>=mod?x+y-mod:x+y;}
int del(int x,int y) {return x-y<0?x-y+mod:x-y;}
int mul(int x,int y) {return 1ll*x*y-1ll*x*y/mod*mod;}
int qpow(int a,int x) {
int res=1;
for(;x;x>>=1,a=mul(a,a)) if(x&1) res=mul(res,a);
return res;
}
namespace poly {
int N,w[maxn],pos[maxn],bit,mxn,t[2][maxn];
void init(int l) {
for(mxn=1;mxn<=l;mxn<<=1) ;
w[0]=1,w[1]=qpow(3,(mod-1)/mxn);
for(int i=2;i<=mxn;i++) w[i]=mul(w[i-1],w[1]);
}
void ntt(int *r,int op) {
FOR(i,1,N-1) if(pos[i]>i) swap(r[pos[i]],r[i]);
for(int i=1,d=mxn>>1;i<N;i<<=1,d>>=1)
for(int j=0;j<N;j+=i<<1)
for(int k=0;k<i;k++) {
int x=r[j+k],y=mul(r[i+j+k],w[k*d]);
r[j+k]=add(x,y),r[i+j+k]=del(x,y);
}
if(op==-1) {
reverse(r+1,r+N);int d=qpow(N,mod-2);
for(int i=0;i<N;i++) r[i]=mul(r[i],d);
}
}
vec pmul(vec a,vec b) {
if(1ll*_sz(a)*_sz(b)<=5000) {
vec c;c.resize(_sz(a)+_sz(b)-1);
FOR(i,0,_sz(a)-1) FOR(j,0,_sz(b)-1) c[i+j]=add(c[i+j],mul(a[i],b[j]));
return c;
}
for(N=1,bit=0;N<_sz(a)+_sz(b);N<<=1,bit++);
FOR(i,0,N-1) pos[i]=pos[i>>1]>>1|((i&1)<<(bit-1));
FOR(i,0,_sz(a)-1) t[0][i]=a[i];FOR(i,_sz(a),N) t[0][i]=0;
FOR(i,0,_sz(b)-1) t[1][i]=b[i];FOR(i,_sz(b),N) t[1][i]=0;
ntt(t[0],1),ntt(t[1],1);
FOR(i,0,N-1) t[0][i]=mul(t[0][i],t[1][i]);
ntt(t[0],-1);vec c;
FOR(i,0,_sz(a)+_sz(b)-1) c.pb(t[0][i]);
return c;
}
vec padd(vec a,vec b) {
if(_sz(a)>_sz(b)) {FOR(i,0,_sz(b)-1) a[i]=add(a[i],b[i]);return a;}
FOR(i,0,_sz(a)-1) b[i]=add(a[i],b[i]);return b;
}
}
ll k;
int n,ch[maxn],head[maxn],tot,sz[maxn],F[maxn],cnt;
struct edge{int to,nxt;}e[maxn<<1];
vec f[maxn],r[maxn];
void ins(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot;}
void dfs(int x,int fa) {
sz[x]=1;F[x]=fa;
for(int i=head[x],v;i;i=e[i].nxt)
if((v=e[i].to)!=fa) {dfs(v,x);sz[x]+=sz[v];if(sz[ch[x]]<sz[v]) ch[x]=v;}
}
void solve(int lt,int rt,vec &a,vec &b) {
if(lt==rt) return a=b=r[lt],void();
vec al,ar,bl,br;int mid=(lt+rt)>>1;solve(lt,mid,al,bl),solve(mid+1,rt,ar,br);
b=poly::pmul(bl,br);a=poly::padd(poly::pmul(ar,bl),al);
}
vec dfs2(int x) {
for(int t=x;t;t=ch[t]) {
for(int i=head[t];i;i=e[i].nxt) if(e[i].to!=F[t]&&e[i].to!=ch[t]) f[t]=dfs2(e[i].to);
if(_sz(f[t])<1) f[t].resize(1);f[t][0]++;
f[t].insert(f[t].begin(),0);
}
cnt=0;for(int t=x;t;t=ch[t]) r[++cnt]=f[t];
vec a,b;solve(1,cnt,a,b);return a;
}
int main() {
read(n),scanf("%lld",&k);poly::init(n<<1);k%=mod;
for(int i=1,x,y;i<n;i++) read(x),read(y),ins(x,y),ins(y,x);
dfs(1,0);vec res=dfs2(1);int t=1,ans=0;
for(int i=1;i<_sz(res);i++) {
ans=add(ans,mul(res[i],t));
t=mul(t,mul((k+i)%mod,qpow(i,mod-2)));
}write(ans);
return 0;
}
Codeforces Round #499 (Div. 1) F. Tree的更多相关文章
- Codeforces Round #527 (Div. 3) F. Tree with Maximum Cost 【DFS换根 || 树形dp】
传送门:http://codeforces.com/contest/1092/problem/F F. Tree with Maximum Cost time limit per test 2 sec ...
- Codeforces Round #527 (Div. 3) . F Tree with Maximum Cost
题目链接 题意:给你一棵树,让你找一个顶点iii,使得这个点的∑dis(i,j)∗a[j]\sum dis(i,j)*a[j]∑dis(i,j)∗a[j]最大.dis(i,j)dis(i,j)dis( ...
- Codeforces Round #499 (Div. 2) F. Mars rover_dfs_位运算
题解: 首先,我们可以用 dfsdfsdfs 在 O(n)O(n)O(n) 的时间复杂度求出初始状态每个点的权值. 不难发现,一个叶子节点权值的取反会导致根节点的权值取反当且仅当从该叶子节点到根节点这 ...
- Codeforces Round #499 (Div. 1)
Codeforces Round #499 (Div. 1) https://codeforces.com/contest/1010 为啥我\(\rm Div.1\)能\(A4\)题还是\(\rm s ...
- Codeforces Round #499 (Div. 2)
Codeforces Round #499 (Div. 2) https://codeforces.com/contest/1011 A #include <bits/stdc++.h> ...
- Codeforces Round #499 (Div. 1)部分题解(B,C,D)
Codeforces Round #499 (Div. 1) 这场本来想和同学一起打\(\rm virtual\ contest\)的,结果有事耽搁了,之后又陆陆续续写了些,就综合起来发一篇题解. B ...
- Codeforces Round #485 (Div. 2) F. AND Graph
Codeforces Round #485 (Div. 2) F. AND Graph 题目连接: http://codeforces.com/contest/987/problem/F Descri ...
- Codeforces Round #486 (Div. 3) F. Rain and Umbrellas
Codeforces Round #486 (Div. 3) F. Rain and Umbrellas 题目连接: http://codeforces.com/group/T0ITBvoeEx/co ...
- Codeforces Round #501 (Div. 3) F. Bracket Substring
题目链接 Codeforces Round #501 (Div. 3) F. Bracket Substring 题解 官方题解 http://codeforces.com/blog/entry/60 ...
随机推荐
- 洛谷P1084 运输计划
题目 题目要求使一条边边权为0时,m条路径的长度最大值的最小值. 考虑二分此长度最大值 首先需要用lca求出树上两点间的路径长度.然后取所有比mid大的路径的交集,判断有哪些边在这些路径上都有出现,然 ...
- java项目里classpath具体指哪儿个路径
一.classpath路径指什么 只知道把配置文件如:mybatis.xml.spring-web.xml.applicationContext.xml等放到src目录(就是存放代码.java文件的目 ...
- Mysql之Incorrect string value: '\xF0\x9F\x98\x89 \xE6... 保存emoji表情
错误信息如下: Incorrect string value: '\xF0\x9F\x98\x89 \xE6...' 问题产生的原因是字符串不兼容4字节的unicode导致的,一般我们常见的表情编码等 ...
- Embed MP4 in HTML using flash-player(html5 video player)
https://stackoverflow.com/questions/1000851/embed-mp4-in-html-using-flash-player ******************* ...
- Android Studio + opencv开发配置
1 下载Android Studio https://developer.android.com/studio/archive?hl=zh-cn 2 安装Android Studio 安装完成,下载S ...
- (原)ffmpeg中filter开发过程遇到的坑<一>
最近在使用ffmpeg开发了一些滤镜filter功能,中间出现一些问题,今天想把这部分的内容整理为笔记,方便以后遇到同样问题的时候,方便翻阅. author:lihaiping1603@aliyun. ...
- intellij查找接口的实现类
拿MyBatis的SqlSession为例 第一步:先找到这个接口 第二步:右击选择 再选择 第三步: 会得到如下 右击Closeable,因为SqlSession实现了它,选择Show Inplem ...
- os.environ详解
我们想要用Python获得一些有关系统的各种信息的时候就不得不想到os的environ,那这里面都具体包含了那些内容呢? 简介 对于官方的解释,environ是一个字符串所对应环境的映像对象.这是什么 ...
- 双写mq后碰到没有消费问题记录
上周双写mq后碰到遇到个问题,mq双写的一台机器有produce,另一台一直没有,但是有的那台机器没有消费者,导致另一个服务 一直没有可以消费的mq.原因是 mq在双写初始化配置的时候两个类文件重复了 ...
- [Swoole入门到进阶] [公开课] Swoole协程-Swoole4.4.4 提供 WaitGroup 功能
在 Swoole4 中可以使用 channel 实现协程间的通信.依赖管理.协程同步. 简单来说,WaitGroup 就是使用 channel 的机制,让主协程等待所有子协程结束后才退出的功能. Co ...