2028E - Alice's Adventures in the Rabbit Hole

可以先从一条链的情况开始观察,然后发现每次都会选深度最小的子节点(minf(v)),可以看作一个短链剖分,不过我不是这么写的
g(v)表示的是f(v)是f(u)的几分之几
我推的式子是这两个,但是我没法证明g(v)不会等于2使得分母为0
但是我觉得因为g(x)一定是合法的所以显然2-g(v)不会为0

\(f(x)=\frac{1}{2}(f(u)+min(f(v))\)
\(g(x)=\frac{1}{2-g(v)}\)

呃上面是我的做法,下面稍微说一下题解做法
短链剖分以后每条链都是一个等差数列,由式子\(f(x)=\frac{1}{2}(f(u)+f(v))\)可知
所以知道链根部的值就可以算链里面每个节点的值,准确来说是用根的f(fa)来算

#include <bits/stdc++.h>
using namespace std;

#define int long long
#define lowbit(x) (x & (-x))
#define pii pair<int, int>
#define mkp make_pair

const int N = 2e5 + 10, mod = 998244353;

int g[N], f[N], n, dep[N];
vector<int> E[N];

int qpow(int x, int y)
{
    int res = 1;
    while (y > 0)
    {
        if (y & 1)
            res = res * x % mod;
        x = x * x % mod;
        y >>= 1;
    }
    return res;
}
int inv(int x)
{
    return qpow(x, mod - 2);
}
int sub(int a, int b)
{
    return (a - b < 0) ? (a - b + mod) : (a - b);
}
int add(int a, int b)
{
    return (a + b > mod) ? (a + b - mod) : (a + b);
}
void dfs(int x, int u)
{
    int mn = 0x3f3f3f3f, flag = -1;
    for (int i : E[x])
    {
        if (i == u)
            continue;
        dfs(i, x);
        if (dep[i] < mn)
            flag = i, mn = dep[i];
    }
    if (x == 1)
    {
        f[x] = 1;
        return;
    }
    if (flag == -1)
    {
        dep[x] = 1;
        f[x] = 0;
        g[x] = 0;
        // cout<<x<<endl;
        return;
    }
    dep[x] = mn + 1;
    // cout<<g[flag]<<endl;
    g[x] = inv(sub(2, g[flag]));
    // cout<<x<<' '<<flag<<' '<<g[flag]<<' '<<g[x]<<endl;
}
void dfs2(int x, int fa)
{
    for (int i : E[x])
    {
        if (i == fa)
            continue;
        f[i] = f[x] * g[i] % mod;
        // cout<<"MK"<<i<<' '<<f[x]<<' '<<g[i]<<endl;
        dfs2(i, x);
    }
    return;
}
void solve()
{
    cin >> n;
    for (int i = 1; i < n; i++)
    {
        int u, v;
        cin >> u >> v;
        E[u].push_back(v);
        E[v].push_back(u);
    }
    dfs(1, 0);
    dfs2(1, 0);
    for (int i = 1; i <= n; i++)
        cout << f[i] << ' ', f[i] = g[i] = dep[i] = 0, E[i].clear();
    cout << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    int T;
    cin >> T;
    while (T--)
        solve();
}

posted @ 2024-11-11 17:27  lyrrr  阅读(25)  评论(0编辑  收藏  举报