1 条题解

  • 0
    @ 2026-8-5 9:50:17

    Solution\Large\text{Solution}

    注意到显然是一层一层扫下去的,类似广搜。

    先考虑每一层内部的点之间如何跳。求出同层点的 LCA,那么必定有这一层的两个点从其中一个到另一个时会经过 LCA,那么每一层内需要的最长路径长度就是这一层到 LCA 的距离乘二。找到所有层中这个最大的一个,记为 mxlenmxlenKK 小于 mxlenmxlen 的时候答案就是 00

    然后考虑两层之间。最劣的情况就是先走到当前层的 LCA,再往下走,长度也就是 mxlen+1mxlen+1。所以 KK 大于 mxlenmxlen 时,每层都可以随意排列,层与层之间相对独立,答案为 cnti!\prod cnt_i!cnticnt_i 为第 ii 层的点数。

    所以只用考虑 KK 刚好等于 mxlenmxlen 时。只考虑那些最长路径等于 mxlenmxlen 的层,其他层也是随意排列。令第 ii 层所有点的 LCA 为 lcailca_i,假设现在在考虑第 xx 层。那么 lcaxlca_x 显然是 lcax+1lca_{x+1} 的祖先且不等于 lcax+1lca_{x+1},否则 mxlenmxlen 不会在第 xx 层取到,也就不会考虑这一层。

    那么我们只需要从 lcaxlca_xlcax+1lca_{x+1} 走一步,在这个点子树内的深度为 xx 的点就可以走到所有深度为 x+1x+1 的点,其他的就不行。那么这个题就做完了。

    Code\Large\text{Code}

    #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
    上传者