构树 题解
构树 题解
好题,除了毒瘤卡空间。
“恰好” 这个形式很二项式反演。设
二项式反演得到:
于是考虑如何求出
考虑
那么容易得到树形 dp:我们设
转移的式子和树形背包是类似的,对于
那么二项式反演即可,时间复杂度是相当于将整棵树每个节点的
考虑这样的空间复杂度也是 std::vector
动态管理内存,每次 vector<int>().swap(v)
释放内存即可。
注意当计数题思路进行不下去的时候考虑某一项的组合意义转化为可以形象求解的问题。
代码:
#include <bits/stdc++.h>
#define N 8005
#define int long long
#define mod 1000000007
using namespace std;
int n;
struct Node {
int to, nxt;
} e[N << 1];
int head[N], cnt;
void add(int u, int v) {
e[++cnt].to = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
void ad(int &x, int y) {
x += y;
if (x > mod)
x -= mod;
}
int siz[N];
int tmp[N][2];
vector<int>v0[N], v1[N];
void dfs(int x, int fa) {
siz[x] = 1;
v0[x].resize(n), v1[x].resize(n);
v0[x][0] = v1[x][0] = 1;
for (int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if (y == fa)
continue;
dfs(y, x);
for (int j = 0; j < siz[x]; j++)
for (int k = 0; k < siz[y]; k++) {
ad(tmp[j + k + 1][0], v0[x][j] * v0[y][k] % mod);
ad(tmp[j + k + 1][1], (v0[x][j] * v1[y][k] % mod + v1[x][j] * v0[y][k] % mod) % mod);
ad(tmp[j + k][0], v0[x][j] * v1[y][k] % mod * n % mod);
ad(tmp[j + k][1], v1[x][j] * v1[y][k] % mod * n % mod);
}
siz[x] += siz[y];
for (int j = 0; j < siz[x]; j++)
v0[x][j] = tmp[j][0], v1[x][j] = tmp[j][1], tmp[j][0] = tmp[j][1] = 0;
vector<int>().swap(v0[y]);
vector<int>().swap(v1[y]);
}
}
int qpow(int x, int y) {
int ans = 1;
while (y) {
if (y & 1)
ans = ans * x % mod;
x = x * x % mod;
y >>= 1;
}
return ans;
}
int fac[N], inv[N];
int C(int n, int m) {
if (n < m)
return 0;
return fac[n] * inv[m] % mod * inv[n - m] % mod;
}
signed main() {
freopen("tree.in", "r", stdin);
freopen("tree.out", "w", stdout);
cin >> n;
fac[0] = inv[0] = 1;
for (int i = 1; i < N; i++)
fac[i] = fac[i - 1] * i % mod, inv[i] = qpow(fac[i], mod - 2);
for (int i = 1; i < n; i++) {
int x, y;
scanf("%lld%lld", &x, &y);
add(x, y);
add(y, x);
}
dfs(1, 0);
const int inv = qpow(n, mod - 2);
for (int i = 0; i < n; i++)
v1[1][i] = v1[1][i] * inv % mod;
for (int i = 0; i < n; i++) {
int fg = 1, ans = 0;
for (int j = i; j < n; j++)
ans = (ans + fg * C(j, i) % mod * v1[1][j] % mod + mod) % mod, fg *= -1;
cout << ans << " ";
}
puts("");
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通