CF1707D Partial Virtual Trees 题解
CF1707D Partial Virtual Trees 题解
知识点
树形 DP,二项式反演,容斥。
分析
容斥
考虑先处理容斥的部分,也就是把集合关系中的 \(\subsetneq\) 转为 \(\subseteq\),这里需要用到容斥和反演。
设:
- \(G(k)\) 表示题目要求的答案。
- \(F(k)\) 表示把题目要求集合关系中的 \(\subsetneq\) 转为 \(\subseteq\) 后的答案。
则有:
\[F(i) = \sum_{j=1}^i {i\choose j} G(j) \\
\]
实际组合意义:表示 \(i\) 个 \(\subseteq\) 中选出 \(j\) 个转为 \(\subsetneq\) 的。
那么根据二项式反演,有:
\[G(i) = \sum_{j=1}^i (-1)^{i-j} {i\choose j} F(j) \\
\]
DP
设 \(f_{u,i}\) 表示在 \(S_i\) 中仍有 \(u\) 子树中的点的方案数,由于题目的特殊性质,要分两种情况讨论,其中第二种容易遗漏。
\(u\) 在 \(S_i\) 中
\[\prod_{v\in son(u)} \sum_{j=0}^{i} f_{v,j} \\
\]
暴力 \(O(n^3)\),前缀和优化至 \(O(n^2)\)。
\(u\) 不在 \(S_i\) 中
发现此时在集合 \(son(u)\) 中只能有一个点 \(v_0\) 满足 \(S_i\) 中有 \(v_0\) 子树中的点,同时还要考虑 \(i\) 在哪个集合删除,则有:
\[\sum_{v_0\in son(u)} f_{v_0,i} \sum_{j=0}^{i-1} \prod_{v\in son(u),v\neq v_0} \sum_{k=0}^{j-1} f_{v,k} \\
\]
暴力 \(O(n^5)\),前缀和、前后缀积优化至 \(O(n^2)\)。
求 \(F(i)\)
注意最后求答案的时候不能简单的把 \(f\) 拿来直接用,因为题目限定了 \(S_k = \set{1}\),所以要再 DP 一下。
\[F(i) = \prod_{v\in son(rt)} \sum_{j=0}^{i-1} f_{v,j} \\
\]
暴力 \(O(n^3)\),前缀和优化至 \(O(n^2)\)。
代码
//#define Plus_Cat ""
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define RCL(a,b,c,d) memset(a,b,sizeof(c)*(d))
#define FOR(i,a,b) for(int i(a);i<=(int)(b);++i)
#define DOR(i,a,b) for(int i(a);i>=(int)(b);--i)
#define tomax(a,...) ((a)=max({(a),__VA_ARGS__}))
#define tomin(a,...) ((a)=min({(a),__VA_ARGS__}))
#define EDGE(g,i,x,y) for(int i=(g).h[(x)],y=(g)[(i)].v;~i;y=(g)[(i=(g)[i].nxt)>0?i:0].v)
#define main Main();signed main(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);return Main();}signed Main
using namespace std;
constexpr int N(2e3+10);
namespace IOEcat {
//Fast IO...
} using namespace IOEcat;
namespace Modular {
int Mod;
int C[N][N];
ll MOD;
//Modular...
int Pow(int a,int b=Mod-2) {
int res(1);
for(a%=Mod; b; b>>=1,tomul(a,a))if(b&1)tomul(res,a);
return res;
}
void Init(const int n=N-5) {
FOR(i,0,n) {
C[i][0]=1;
FOR(j,1,i)C[i][j]=add(C[i-1][j-1],C[i-1][j]);
}
}
} using namespace Modular;
int n,m;
int F[N];
int f[N][N];
vector<int> g[N];
void dfs(int u,int fa) {
for(const int &v:g[u])if(v^fa)dfs(v,u);
int tot(0);
static int son[N],sum[N];
for(const int &v:g[u])if(v^fa)son[++tot]=v;
f[u][0]=1;
FOR(i,1,m) {
/*DE("Update");*/
int cur(1);
static int pre[N];
FOR(j,pre[0]=1,tot)pre[j]=mul(pre[j-1],f[son[j]][i-1]);
DOR(j,tot,1)toadd(sum[son[j]],mul(pre[j-1],cur)),tomul(cur,f[son[j]][i-1]);
/*DE("Trans");*/
f[u][i]=1;
FOR(j,1,tot)tomul(f[u][i],f[son[j]][i]);
FOR(j,1,tot)toadd(f[u][i],mul(add(f[son[j]][i],Mod-f[son[j]][i-1]),sum[son[j]]));
toadd(f[u][i],f[u][i-1]);
}
}
signed main() {
#ifdef Plus_Cat
freopen(Plus_Cat ".in","r",stdin),freopen(Plus_Cat ".out","w",stdout);
#endif
I(n,Mod),m=n-1,MOD=((__int128)1<<64)/Mod,Init();
FOR(i,2,n) {
int u,v;
I(u,v),g[u].push_back(v),g[v].push_back(u);
}
for(const int &v:g[1])dfs(v,1);
FOR(i,1,m) {
F[i]=1;
for(const int &v:g[1])tomul(F[i],f[v][i-1]);
}
FOR(i,1,m) {
int ans(0);
FOR(j,1,i)(i^j)&1?toadd(ans,Mod-mul(C[i][j],F[j])):toadd(ans,mul(C[i][j],F[j]));
O(ans,' ');
}
return 0;
}

浙公网安备 33010602011771号