1 条题解
-
0
注意到显然是一层一层扫下去的,类似广搜。
先考虑每一层内部的点之间如何跳。求出同层点的 LCA,那么必定有这一层的两个点从其中一个到另一个时会经过 LCA,那么每一层内需要的最长路径长度就是这一层到 LCA 的距离乘二。找到所有层中这个最大的一个,记为 , 小于 的时候答案就是 。
然后考虑两层之间。最劣的情况就是先走到当前层的 LCA,再往下走,长度也就是 。所以 大于 时,每层都可以随意排列,层与层之间相对独立,答案为 , 为第 层的点数。
所以只用考虑 刚好等于 时。只考虑那些最长路径等于 的层,其他层也是随意排列。令第 层所有点的 LCA 为 ,假设现在在考虑第 层。那么 显然是 的祖先且不等于 ,否则 不会在第 层取到,也就不会考虑这一层。
那么我们只需要从 往 走一步,在这个点子树内的深度为 的点就可以走到所有深度为 的点,其他的就不行。那么这个题就做完了。
#include <bits/stdc++.h> //#define int long long #define x first #define y second using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair <int, int> pii; typedef pair <int, pii> piii; const double PI = acos (-1); const double eps = 1e-10; const int N = 5e5 + 10, M = 2e5 + 10; const int mod = 1e9 + 7; //const int mod = 998244353; vector <int> v[N], g[N]; int d[N], lca[N], maxd, mxlen; int st[N][19]; ll fac[N]; void dfs(int u, int fa) { d[u] = d[fa] + 1, maxd = max (maxd, d[u]); g[d[u]].push_back (u), st[u][0] = fa; for (int i = 1; i <= 18; i++) st[u][i] = st[st[u][i - 1]][i - 1]; for (int j : v[u]) if (fa != j) dfs (j, u); } int LCA(int a, int b) { if (d[a] < d[b]) swap (a, b); for (int i = 18; i >= 0; i--) if (d[st[a][i]] >= d[b]) a = st[a][i]; if (a == b) return a; for (int i = 18; i >= 0; i--) if (st[a][i] != st[b][i]) a = st[a][i], b = st[b][i]; return st[a][0]; } bool check(int a, int b) { for (int i = 18; i >= 0; i--) if (d[st[a][i]] >= d[b]) a = st[a][i]; return a == b; } signed main() { cin.tie (0), cout.tie (0); ios :: sync_with_stdio (false); int t; cin >> t; fac[0] = 1; for (int i = 1; i < N; i++) fac[i] = fac[i - 1] * i % mod; while (t--) { int n, q; cin >> n >> q; maxd = mxlen = 0; for (int i = 1; i <= n; i++) lca[i] = 0, v[i].clear (), g[i].clear (); for (int i = 1; i < n; i++) { int x, y; cin >> x >> y; v[x].push_back (y); v[y].push_back (x); } dfs (1, 0); ll ansa = 1, ansb = 1; for (int i = 1; i <= maxd; i++) ansb = ansb * fac[g[i].size ()] % mod; for (int i = 1; i <= n; i++) if (lca[d[i]]) lca[d[i]] = LCA (lca[d[i]], i); else lca[d[i]] = i; for (int i = 1; i <= maxd; i++) mxlen = max (mxlen, 2 * (i - d[lca[i]])); for (int i = 1; i < maxd; i++) { if (2 * (i - d[lca[i]]) == mxlen) { int cnt = 0, anc = lca[i + 1]; for (int j = 18; j >= 0; j--) if (d[st[anc][j]] > d[lca[i]]) anc = st[anc][j]; for (int j : g[i]) cnt += check (j, anc); ansa = ansa * cnt % mod * fac[g[i].size () - 1] % mod; } else ansa = ansa * fac[g[i].size ()] % mod; } ansa = ansa * fac[g[maxd].size ()] % mod; while (q--) { int x; cin >> x; if (x < mxlen) cout << "0 "; else if (x == mxlen) cout << ansa << " "; else cout << ansb << " "; } cout << "\n"; } return 0; }
- 1
信息
- ID
- 12590
- 时间
- 4000ms
- 内存
- 600MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者