1 条题解
-
0
注意到每个结点由唯一的水豚管理一定是不劣的,一只水豚管理超过 个结点一定可以构造吃不到橙子的情况。
于是问题转化成:将该树划分成若干个大小不超过 的连通块,每个连通块染黑一个点,求染色的方案数。
考虑到 ,不妨设 表示: 的子树中,染了 个点,点 和父亲一个联通块且 不染色的方案数 / 点 与儿子一个连通块的方案数 / 点 是黑点且不与儿子在一个连通块的方案数。
然后就变成树形背包了,复杂度 。
AC 代码(
#define int要记得undef)。#include <bits/stdc++.h> #define fi first #define se second #define mid ((l+r)>>1) #define bmid ((l+r+1)>>1) #define pb push_back #define eb emplace_back using namespace std; using ll= long long; #ifndef ONLINE_JUDGE template <typename tp> void _debug(const tp& t) {cerr<<t<<'\n';} template <typename tp,typename... args> void _debug(const tp& t, const args&... rest) {cerr<<t<<' ';_debug(rest...);} #define debug(...) _debug(#__VA_ARGS__ " =", __VA_ARGS__) #else #define debug(...) 0 #endif #define int ll const int N=6005,H=N<<2,inf=1000000000,mod=998244353; inline void add(int& x,ll y) { x=(x+y)%mod; } vector<int> gr[N]; int siz[N],f[N][N][3],g[N][3]; void cut(int i) { for(int j=0;j<N;j++) for(int k=0;k<3;k++) { g[j][k]=f[i][j][k]; f[i][j][k]=0; } } void dfs(int u,int fa) { siz[u]=1,f[u][0][0]=f[u][1][2]=1; for(int& v: gr[u]) if(v!=fa) { dfs(v,u); cut(u); for(int i=0;i<=siz[u];i++) { for(int j=0;j<=siz[v];j++) { add(f[u][i+j][0],g[i][0]*f[v][j][1]); add(f[u][i+j][1],g[i][0]*f[v][j][2]); add(f[u][i+j][1],g[i][1]*(f[v][j][1]+f[v][j][2])); add(f[u][i+j][1],g[i][2]*f[v][j][0]); add(f[u][i+j][2],g[i][2]*(f[v][j][1]+f[v][j][2])); } } siz[u]+=siz[v]; } } #undef int std::vector<int> solve(int N,std::vector<int> U,std::vector<int> V) { for(int i=0;i+1<N;i++) { U[i]++,V[i]++; gr[U[i]].pb(V[i]),gr[V[i]].pb(U[i]); } dfs(1,0); std::vector<int> ret(N+1); for(int i=0;i<=N;i++) ret[i]=(f[1][i][1]+f[1][i][2])%mod; return ret; } //signed main() { // cin.tie(nullptr)->sync_with_stdio(false); // int nn; // vector<int> u,v; // cin>>nn; // for(int x,y,i=1;i<nn;i++) { // cin>>x>>y; // u.pb(x),v.pb(y); // } // for(int i: solve(nn,u,v)) cout<<i<<' '; // return 0; //}
- 1
信息
- ID
- 9618
- 时间
- 750ms
- 内存
- 1512MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者